一、什么是CAN?
CAN是Controller Area Network的缩写。是一种串行通信协议,在车载行业中有广泛的应用,主要连接不同的控制单元和传感器。
二、CAN的通信协议
CAN通信主要有四种帧格式:数据帧、遥控帧(远程帧)、错误帧、过载帧。其中,数据帧和远程帧有标准格式和扩展格式,此外,部分文档有介绍第五种帧:间隔帧。本文暂时针对标准的数据帧进行调试说明
三、CAN的应用
本次对CAN的研究,主要基于项目需求,研究设备间通过CAN通信进行数据传输做一些笔记。
平台:STM32F103C8/ STM32F103RC/ STM32F103ZE
设备:一台主机多台从机,从机接收到数据时进行相应,不做主动发送。主机可以对从机数据进行查询,对从机设备进行一些参数的设置
扩展:CAN网络中的设备维护
需注意:
1、CAN标准的数据帧一次只能传输8字节,数据较多的时候,需要进行分包处理,数据要进行有效性判断,设定缓存清空条件
2、CAN没有所谓的主机和从机概念,可以分配ID进行自定义主机和从机。ID分配合理,数据过滤会更加方便
3、CAN一些基础知识的了解
四、CAN参数
波特率的计算:
1、确定时钟,阅读ST32F103XX的datasheet,外设CAN使用PCLK1(APB1),内部时钟一般是8MHz经过倍频(9倍频)可以达到72MHz,PCLK1经过72MHz的2分频达到36MHz。
相关代码:
RCC_PCLK1Config(RCC_HCLK_Div2);/* 设置APB1预分频:2 */
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);/* 输入源:HSE,倍频系数:9 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); /* 开启外设时钟 */
2、CAN波特率一些参数的设置
SS:同步段,固定1Tq
SJW:再次同步段,1~4Tq
BS1,BS2:相位缓冲段,BS1(1~8Tq),BS2(2~8Tq)
Prescaler:采样点
波特率 = CAN时钟/((SJW+BS1+BS2)*Prescaler)
备注:这里说的BS1,指代官方文档说的BS1+1tq
相关代码:
CAN_InitTypeDef CAN_InitStructure;
CAN_DeInit(CAN1);/* reset all configuration */
/* 72MHz时钟经过2分频得到36MHz 外设时钟,波特率=36M/((1+3+2)*30)=200K*/
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
CAN_InitStructure.CAN_Prescaler = 30;
滤波器的使用:
本人对于滤波器的使用并未深入,这里只做简单的使用介绍。
滤波器应用于接收的滤波,关闭滤波器的时候,对所有数据都进行接收,开启时,只接收特定ID的数据。
1.标准模式下的ID
范围为:0~0x7FF,在滤波器中CAN_FxR1[31:21],以32位滤波器举例,如下图
2.可变位宽
16位滤波器或32位滤波器
3.标识符列表模式和屏蔽位模式
标识符列表模式:符合固定ID的数据才进行接收,可以理解为每一位都要检验。
屏蔽位模式:对ID中的某些位进行检查,符合预期数据才进行接收。
相关代码:
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber=0;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=id<<5;
CAN_FilterInitStructure.CAN_FilterIdLow=0;
/* xxx1 1111 0000 00xx ,置1表示进行检验的值,置0表示不进行检验。0x1F00表示 对 id&0x1F00进行检验,后面6位不关心,例如id=0x40,则0x40~0x7F都可以接收到 */
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x1F00;//0x1FFC
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure); /* 载入设置 */
中断:
1.初始化中断及优先级
相关代码:
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
接收缓存:CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
中断处理
if(CAN_GetITStatus(CAN1,CAN_IT_FMP0)!= RESET)
{
/* clear irq flag */
CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
/* get message from mailbox */
CAN_Receive(CAN1,CAN_FIFO0,&g_canRx);
}
此外还有CAN的IO配置,管脚映射等,这里不在进行赘述!