一、概述由于项目需要在机车6A系统上运行,故在产品开发时需要用到STM32 bxCAN外设,总体来说STM32的CAN总线应用起来不是很复杂,仔细看资料很容易上手,并且有官方参考例程。
二、底层配置详解
2.1 GPIO初始化
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource8,GPIO_AF_CAN1);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource9,GPIO_AF_CAN1);
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType= GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
2.2 CAN单元初始化
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
CAN_InitStructure.CAN_TTCM = DISABLE;//禁止时间触发通信模式
CAN_InitStructure.CAN_ABOM = DISABLE;//禁止自动离线
CAN_InitStructure.CAN_AWUM = DISABLE;//禁止自动唤醒模式
CAN_InitStructure.CAN_NART = DISABLE;//禁止自动重传
CAN_InitStructure.CAN_RFLM = DISABLE;//接收FIFO锁定
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
2.3 CAN通信波特率设置
CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
CAN_InitStructure.CAN_Prescaler = 2;
CAN_Init(CAN1, &CAN_InitStructure);
2.4 CAN通信滤波器设置
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
2.5 使能FIFO0信息挂起中断
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
三、CAN模块接收中断函数
描述:每次接收8个字节,可以为标准帧或扩展帧。
CanRxMsg RxMessage;
void CAN1_RX0_IRQHandler(void)
{
uint8_t i;
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
for(i=0;i
{
CAN_RxBuffer[i] = RxMessage.Data[i];
}
}
四、CAN发送函数
描述:1、每次发送8个字节。
2、变量tmpID为用户设置的扩展帧ID号。
CanTxMsg TxMessage;
void CAN_TransmitZDJCMessage(uint32_t tmpID)
{
uint8_t TransmitMailbox = 0;
TxMessage.StdId = tmpID>>18;
TxMessage.ExtId = tmpID&0x0003FFFF;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_EXT;
TxMessage.DLC = 8;
TxMessage.Data[0]=1;
TxMessage.Data[1]=2
TxMessage.Data[2]=3;
TxMessage.Data[3]=4;
TxMessage.Data[4]=5;
TxMessage.Data[5]=6;
TxMessage.Data[6]=7;
TxMessage.Data[7]=8;
TransmitMailbox = CAN_Transmit(CAN1, &TxMessage);
while(CAN_TransmitStatus(CAN1,TransmitMailbox)!=1);
}
五、总结
本博文给出的CAN通信实例是经过修改后的程序,并非本人在项目中所使用的,当然项目中使用的程序比本博文写出的代码要复杂的多,并且做了通信超时措施。但本人可以保证本博文给出的历程是完全可以正常通信的,读者朋友可以根据自己的需求进行修改,如有问题可以留言。