//============================================================================ //函数名称: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; }
/*********************************************************************************************** 功能:CAN 初始化 形参:CAN_InitStruct: CAN 初始化结构 返回:0 详解:0 ************************************************************************************************/ void CAN_Init(CAN_InitTypeDef* CAN_InitStruct) { uint8_t i = 0; PORT_Type *CAN_PORT = NULL; CAN_MapTypeDef *pCAN_Map = (CAN_MapTypeDef*)&(CAN_InitStruct->CANxMap); CAN_Type *CANx = NULL; //参数检测 assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->FilterEnable)); assert_param(IS_CAN_MAP(CAN_InitStruct->CANxMap)); assert_param(IS_CAN_SPEED(CAN_InitStruct->CAN_BaudRateSelect)); //找出CAN模块 开启CAN模块时钟 switch(pCAN_Map->CAN_Index ) { case 0: SIM->SCGC6 |= SIM_SCGC6_FLEXCAN0_MASK; CANx = CAN0; break; case 1: SIM->SCGC3 |= SIM_SCGC3_FLEXCAN1_MASK; CANx = CAN1; break; default:break; } //找出对应的PORT switch(pCAN_Map->CAN_GPIO_Index) { case 0: SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK; CAN_PORT = PORTA; break; case 1: SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; CAN_PORT = PORTB; break; case 2: SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK; CAN_PORT = PORTC; break; case 3: SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK; CAN_PORT = PORTD; break; case 4: SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK; CAN_PORT = PORTE; break; default:break; } //开启对应的引脚 CAN_PORT->PCR[pCAN_Map->CAN_TX_Pin_Index] &= ~PORT_PCR_MUX_MASK; CAN_PORT->PCR[pCAN_Map->CAN_RX_Pin_Index] &= ~PORT_PCR_MUX_MASK; CAN_PORT->PCR[pCAN_Map->CAN_TX_Pin_Index] |= PORT_PCR_MUX(pCAN_Map->CAN_Alt_Index); CAN_PORT->PCR[pCAN_Map->CAN_RX_Pin_Index] |= PORT_PCR_MUX(pCAN_Map->CAN_Alt_Index); //选择为BusClock时钟 CANx->CTRL1 |= CAN_CTRL1_CLKSRC_MASK; //使能冻结模式 只有进入冻结模式才能配置波特率 CANx->MCR|=CAN_MCR_FRZ_MASK; //开启CAN通信模块 CANx->MCR &= ~CAN_MCR_MDIS_MASK; //等待通信模块复位启动 while((CAN_MCR_LPMACK_MASK & (CANx->MCR))); //软件复位模块 //等待软件复位完成 CANx->MCR |= CAN_MCR_SOFTRST_MASK; while(CAN_MCR_SOFTRST_MASK & (CANx->MCR)); // 等待模块进入冻结模式 while(!(CAN_MCR_FRZACK_MASK & (CANx->MCR))); for(i=0;i<16;i++) { CANx->MB[i].CS = 0x00000000; CANx->MB[i].ID = 0x00000000; CANx->MB[i].WORD0 = 0x00000000; CANx->MB[i].WORD1 = 0x00000000; } //配置远程请求产生,接收邮箱过滤ide,远程请求不比较, //邮箱首先从接收fifo匹配后再邮箱中匹配见参考手册 CANx->CTRL2 = (0|CAN_CTRL2_TASD(22)); //配置ID模式,目前选择的是A格式 //按照工作要求配置MCR寄存器 CANx->MCR |= CAN_MCR_IDAM(0); //使能个别滤波和接受队列特点? //配置通信频率和初始化CTRL1 (自己理解的,设置传输一bite的时间) |CAN_CTRL1_LPB_MASK CANx->MCR |= CAN_MCR_IRMQ_MASK; //设置传输速率 CAN_SetBaudrate(CANx,CAN_InitStruct->CAN_BaudRateSelect); CANx->MCR |= CAN_MCR_IDAM(0); //配置ID模式,目前选择的是A格式 //设置屏蔽功能 if(CAN_InitStruct->FilterEnable == ENABLE) { for(i = 0; i < 16 ; i++) { CANx->RXIMR[i] = 0x1FFFFFFF; //设置16个接收id的掩码寄存器 CANx->RXMGMASK = 0x1FFFFFFF; } } else { for(i = 0; i < 16 ; i++) { CANx->RXIMR[i] = 0; //设置16个接收id的掩码寄存器 CANx->RXMGMASK = 0; } } //只有在冻结模式下才能配置 配置完退出冻结模式 CANx->MCR &= ~(CAN_MCR_HALT_MASK); //等待模块推出冻结模式 while((CAN_MCR_FRZACK_MASK & (CANx->MCR))); //等待同步 while(((CANx->MCR)&CAN_MCR_NOTRDY_MASK)); //设置接收ID过滤功能 }