//============================================================================ //函数名称:CANInit //函数返回:0:成功;1:失败 //参数说明: // CANChannel:模块号 // baudrateKHz: 波特率 // selfLoop: 模式选择(1=回环模式;0=正常模式) // idMask: ID过滤(1=ID过滤;0=ID不过滤) //功能概要:CAN初始化 //============================================================================ uint8 CANInit(uint8 CANChannel,uint32 baudrateKHz,uint8 selfLoop,uint8 idMask) { int8 i; CAN_MemMapPtr CANBaseAdd; //使能FlexCAN外部时钟 OSC_CR |= OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK; //通过模块号选择模块基地址 if(CANChannel == 0) CANBaseAdd = CAN0_BASE_PTR; else if(CANChannel == 1) CANBaseAdd = CAN1_BASE_PTR; //使能CAN模块时钟 if(CANBaseAdd == CAN0_BASE_PTR) SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0_MASK;//使能CAN0的时钟模块 else SIM_SCGC3 |= SIM_SCGC3_FLEXCAN1_MASK;//使能CAN1的时钟模块 //使能CAN中断 if(CANChannel == 0)//使能CAN0的中断 { NVICICPR0 = (NVICICPR0 & ~(0x07<<29)) | (0x07<<29);//清除挂载在FlexCAN0的中断 NVICISER0 = (NVICISER0 & ~(0x07<<29)) | (0x07<<29);//使能FlexCAN0中断 NVICICPR1 = (NVICICPR1 & ~(0x1F<<0)) | (0x1F);//清除挂载在FlexCAN0的中断 NVICISER1 = (NVICISER1 & ~(0x1F<<0)) | (0x1F);//使能FlexCAN0中断 } else //使能CAN1的中断 { NVICICPR1 = (NVICICPR1 & ~(0xFF<<5)) | (0xFF<<5);//清除挂载在FlexCAN1的中断 NVICISER1 = (NVICISER1 & ~(0xFF<<5)) | (0xFF<<5);//使能FlexCAN1中断 } //配置CAN_RX/TX复用引脚功能 if(CANChannel == 0) { PORTA_PCR12 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //上拉 PORTA_PCR13 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //上拉 } else { PORTE_PCR24 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //Tx上拉 PORTE_PCR25 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //Rx上拉 } //选择时钟源,外设时钟48MHz,内部时钟:12MHz CAN_CTRL1_REG(CANBaseAdd) |= CAN_CTRL1_CLKSRC_MASK;//选择内部时钟 CAN_MCR_REG(CANBaseAdd) |= CAN_MCR_FRZ_MASK; //使能冻结模式 CAN_MCR_REG(CANBaseAdd) &= ~CAN_MCR_MDIS_MASK;//使能CAN模块 //确认已退出冻结模式 while((CAN_MCR_LPMACK_MASK & CAN_MCR_REG(CANBaseAdd))); //软件复位 CAN_MCR_REG(CANBaseAdd) ^= CAN_MCR_SOFTRST_MASK; //等待复位完成 while(CAN_MCR_SOFTRST_MASK & CAN_MCR_REG(CANBaseAdd)); //等待进入冻结模式 while(!(CAN_MCR_FRZACK_MASK & CAN_MCR_REG(CANBaseAdd))); //将16个邮箱缓冲区内容清0 for(i=0;i<16;i++) { CANBaseAdd->MB[i].CS = 0x00000000; CANBaseAdd->MB[i].ID = 0x00000000; CANBaseAdd->MB[i].WORD0 = 0x00000000; CANBaseAdd->MB[i].WORD1 = 0x00000000; } //接收邮箱过滤IDE比较,RTR不比较 CAN_CTRL2_REG(CANBaseAdd) &= ~CAN_CTRL2_EACEN_MASK; //远程请求帧产生 CAN_CTRL2_REG(CANBaseAdd) &= ~CAN_CTRL2_RRS_MASK; //邮箱首先从接收FIFO队列匹配然后再在邮箱中匹配 CAN_CTRL2_REG(CANBaseAdd) &= ~CAN_CTRL2_MRP_MASK; //使用一个32位过滤器 CAN_MCR_REG(CANBaseAdd) |= (CAN_MCR_REG(CANBaseAdd) & ~CAN_MCR_IDAM_MASK) | CAN_MCR_IDAM(0); //设置波特率 if(SetCANBand(CANChannel,baudrateKHz) == 1)//若设置错误 return 1; //模式选择:回环模式或正常模式 if(1==selfLoop) CAN_CTRL1_REG(CANBaseAdd) |= CAN_CTRL1_LPB_MASK;//使用回环模式 //初始化掩码寄存器 if(1==idMask)//屏蔽ID { CAN_RXMGMASK_REG(CANBaseAdd) = 0x1FFFFFFF; CAN_RX14MASK_REG(CANBaseAdd) = 0x1FFFFFFF; CAN_RX15MASK_REG(CANBaseAdd) = 0x1FFFFFFF; } else//不屏蔽ID { CAN_RXMGMASK_REG(CANBaseAdd) = 0x0; CAN_RX14MASK_REG(CANBaseAdd) = 0x0; CAN_RX15MASK_REG(CANBaseAdd) = 0x0; } //如果单独掩码功能使能,为每个队列初始化单独的掩码寄存器 if(CAN_MCR_REG(CANBaseAdd) & CAN_MCR_IRMQ_MASK) { for(i = 0; i < NUMBER_OF_MB ; i++) { CANBaseAdd->RXIMR[i] = 0x1FFFFFFFL; } } //只有在冻结模式下才能配置,配置完推出冻结模式 CAN_MCR_REG(CANBaseAdd) &= ~(CAN_MCR_HALT_MASK); //等待直到退出冻结模式 while( CAN_MCR_REG(CANBaseAdd) & CAN_MCR_FRZACK_MASK); //等到不在冻结模式,休眠模式或者停止模式 while((CAN_MCR_REG(CANBaseAdd) & CAN_MCR_NOTRDY_MASK)); return 0; }
/* * LPLD_CAN_Init * 该函数用于Flex_CAN模块初始化 * 参数: * canx--设置CAN模块号 * |__CAN0 --CAN0号模块 * |__CAN1 --CAN1号模块 * baud_khz--设置CAN总线波特率 * |__0 * |__.... * selfloop--设置CAN总线自循环模式 * |__CAN_NOSELFLOOP --不循环 * |__CAN_SELFLOOP --循环 * 输出: * 0:配置出现错误 * 1:配置成功 */ uint8 LPLD_CAN_Init(CANx canx, uint32 baud_khz, uint8 selfloop) { int8 i; CAN_MemMapPtr canptr = CANx_Ptr[canx]; //使能FlexCAN外部时钟 OSC_CR |= OSC_CR_ERCLKEN_MASK | OSC_CR_EREFSTEN_MASK; //使能CAN模块时钟 if(canx == CAN0) SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0_MASK;//使能CAN0的时钟模块 else SIM_SCGC3 |= SIM_SCGC3_FLEXCAN1_MASK;//使能CAN1的时钟模块 //配置CAN_RX/TX复用引脚功能 if(canx == CAN0) { //CAN0_TX PORTA_PCR12 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //Tx上拉 //CAN0_RX PORTA_PCR13 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //RX上拉 } else { PORTE_PCR24 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //Tx上拉 PORTE_PCR25 = PORT_PCR_MUX(2) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; //Rx上拉 } //注:CTRL1不能在FRZ(冻结)模式下设置 //选择时钟源,外设时钟48MHz,内部时钟:12MHz //选择内部时钟 CAN_CTRL1_REG(canptr)|= CAN_CTRL1_CLKSRC_MASK; //使能CAN模块 CAN_MCR_REG(canptr) &= ~CAN_MCR_MDIS_MASK; //在时钟初始化完毕和CAN总线使能完毕后, //单片机自动进入冻结模式 //只有在冻结模式下才能配置大多数CAN总线寄存器 //使能冻结模式 CAN_MCR_REG(canptr) |= CAN_MCR_FRZ_MASK; //确认不在低功耗模式,如果在低功耗模式下软件复位无法完成 while((CAN_MCR_REG(canptr) & CAN_MCR_LPMACK_MASK )); //软件复位 //受影响的registers: MCR (except the MDIS bit), TIMER, ECR, ESR1, ESR2, // IMASK1, IMASK2, IFLAG1, IFLAG2 and CRCR. //不受影响的registers:CTRL1, CTRL2, RXIMR0–RXIMR63, RXMGMASK, RX14MASK, // RX15MASK, RXFGMASK, RXFIR, all Message Buffers //复位后MCR中RFEN=0,因而Rx FIFO并没有使能 --------重要 //因而“使能冻结模式位”被复位 //CAN 总线软件复位,复位后该自动清零 CAN_MCR_REG(canptr) |= CAN_MCR_SOFTRST_MASK; //等待复位完成 while(CAN_MCR_SOFTRST_MASK & CAN_MCR_REG(canptr)); //退出正常模式,再次使能冻结模式 ,因为软件复位使冻结模式退出 CAN_MCR_REG(canptr) |= CAN_MCR_FRZ_MASK; //等待进入冻结模式 while(!(CAN_MCR_REG(canptr) & CAN_MCR_FRZACK_MASK)); //=================Initialize the Module Configuration Register============= //1 Enable the individual filtering per MB and reception queue features by setting the IRMQ bit //1设置全匹配蔽位,并配置与之相关的寄存器 CAN_CTRL2_REG(canptr) &= ~CAN_CTRL2_EACEN_MASK;//接收邮箱过滤IDE匹配,RTR不匹配 CAN_CTRL2_REG(canptr) &= ~CAN_CTRL2_RRS_MASK; //不自动产生远程请求帧产生 CAN_MCR_REG(canptr) &= ~CAN_MCR_IRMQ_MASK; //使能全局匹配寄存器 CAN_CTRL2_REG(canptr) |= CAN_CTRL2_MRP_MASK; //ID首先从邮箱中匹配 CAN_CTRL1_REG(canptr) |= CAN_CTRL1_LBUF_MASK; //发送的时候从低优先级发送 CAN_RXMGMASK_REG(canptr) = 0x1FFFFFFF; //28位ID全部匹配 CAN_RX14MASK_REG(canptr) = 0x00000000; CAN_RX15MASK_REG(canptr) = 0x00000000; //2 WRN_EN bit //2设置是否产生警告中断 CAN_MCR_REG(canptr) &= ~CAN_MCR_WRNEN_MASK; //不产生警告中断 //3 SRX_DIS bit //3设置是否自我接受 //CAN_MCR_REG(canptr) |= CAN_MCR_SRXDIS_MASK; //禁止CAN自我接收 //4 Enable the Rx FIFO by setting the RFEN bit //4 设置是否使能RX FIFO CAN_MCR_REG(canptr) &= ~CAN_MCR_RFEN_MASK ; //禁止接收FIFO //5 Enable the abort mechanism by setting the AEN bit CAN_MCR_REG(canptr) &= ~CAN_MCR_AEN_MASK; //6 Enable the local priority feature by setting the LPRIO_EN bit CAN_MCR_REG(canptr) &= ~CAN_MCR_LPRIOEN_MASK; //模式选择:回环模式或正常模式 if(selfloop) CAN_CTRL1_REG(canptr) |= CAN_CTRL1_LPB_MASK; //使用回环模式 else CAN_CTRL1_REG(canptr) &= ~CAN_CTRL1_LPB_MASK; //使用正常模式 //->Initialize the Control Register //Determine the bit timing parameters: PROPSEG, PSEG1, PSEG2, RJW //Determine the bit rate by programming the PRESDIV field //Determine the internal arbitration mode (LBUF bit) //设置波特率 if(LPLD_CAN_SetBaud(canx,baud_khz))//若设置错误 { return 0; } //“SYNC” message 使能同步功能 CAN_MCR_REG(canptr) |= CAN_CTRL1_TSYN_MASK; CAN_TIMER_REG(canptr) = 0x0000; //->Initialize the Message Buffers //The Control and Status word of all Message Buffers must be initialized //If Rx FIFO was enabled, the ID filter table must be initialized //Other entries in each Message Buffer should be initialized as required //将16个邮箱缓冲区内容清0 for(i=0;i<16;i++) { canptr->MB[i].CS = 0x00000000; canptr->MB[i].ID = 0x00000000; canptr->MB[i].WORD0 = 0x00000000; canptr->MB[i].WORD1 = 0x00000000; } //初始化所需要的接受邮箱,设置邮箱的ID,即filter的ID值 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_1,FILTER_SLAVEA_ID);//1 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_2,FILTER_SLAVEB_ID);//2 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_3,FILTER_SLAVEC_ID);//3 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_4,FILTER_SLAVED_ID);//4 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_5,FILTER_SLAVEE_ID);//5 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_6,FILTER_SLAVEF_ID);//6 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_7,FILTER_SLAVEG_ID);//7 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_8,FILTER_SLAVEH_ID);//8 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_9,FILTER_SLAVEI_ID);//9 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_10,FILTER_SLAVEJ_ID);//10 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_11,FILTER_SLAVEK_ID);//11 LPLD_CAN_Enable_RX_Buf(canx,MB_NUM_12,FILTER_SLAVEL_ID);//12 //->Initialize the Rx Individual Mask Registers //设置每个邮箱的匹配寄存器,用到那个邮箱设置哪给 canptr->RXIMR[0] = 0x00000000; canptr->RXIMR[1] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[2] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[3] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[4] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[5] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[6] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[7] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[8] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[9] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[10] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[11] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[12] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[13] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[14] = 0x1FFFFFFF; //设置28位屏蔽位 canptr->RXIMR[15] = 0x1FFFFFFF; //设置28位屏蔽位 //Set required interrupt mask bits in the IMASK Registers (for all MB interrupts), in //CTRL Register (for Bus Off and Error interrupts) and in MCR Register for Wake-Up interrupt //清除所有邮箱的标志位 LPLD_CAN_ClearAllFlag(canx); //使能接受邮箱中断 LPLD_CAN_Enable_Interrupt(canx,MB_NUM_1); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_2); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_3); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_4); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_5); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_6); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_7); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_8); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_9); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_10); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_11); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_12); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_13); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_14); LPLD_CAN_Enable_Interrupt(canx,MB_NUM_15); //Negate the HALT bit in MCR //只有在冻结模式下才能配置,配置完推出冻结模式 CAN_MCR_REG(canptr) &= ~(CAN_MCR_HALT_MASK); //等待直到退出冻结模式 while( CAN_MCR_REG(canptr) & CAN_MCR_FRZACK_MASK); //等到不在冻结模式,休眠模式或者停止模式 while((CAN_MCR_REG(canptr) & CAN_MCR_NOTRDY_MASK)); //Starting with the last event, FlexCAN attempts to synchronize to the CAN bus. return 1; }