CAN总线协议入门基础原理

CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO*1 国际标准化的串行通信协议。CAN 通过 ISO11898 及 ISO11519 进行了标准化,现在在欧洲已是汽车网络的标准协议。现在,CAN 的高性能和可靠性已被认同,并被广泛地应用于汽车电子、工业自动化、船舶、医疗设备、工业设备等方面。

从CAN总线拓扑图中可以知道, CAN 控制器根据两根线上的电位差来判断总线电平。总线电平分为显性电平(0)和隐性电平(1),二者必居其一。发送方通过使总线电平发生变化,将消息发送给接收方。

图1 CAN总线拓扑图

CAN 协议特点

(1) 多主控制: 在总线空闲时,所有的单元都可开始发送消息(多主控制)。 最先访问总线的单元可获得发送权(CSMA/CA 方式)。 多个单元同时开始发送时,发送高优先级 ID 消息的单元可获得发送权。

(2) 消息的发送: 在串口通信协议中,数据的收发是没有固定的数据格式的,而在 CAN 协议中,所有的消息都以固定的格式发送。总线空闲时,所有与总线相连的单元都可以开始发送新 消息。两个以上的单元同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级。与IIC总线协议不同,ID 并不是表示发送的目的地址(设备地址),而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。

(3) 系统的柔软性: 与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬 件及应用层都不需要改变。

(4) 通信速度: 根据整个网络的规模,可设定适合的通信速度。 在同一网络中,所有单元必须设定成统一的通信速度。即使有一个单元的通信速度与其它的不一样,此单元也会输出错误信号,妨碍整个网络的通信。不同网络间则可以有不同的通信速度。

(5) 远程数据请求: 可通过发送“遥控帧” 请求其他单元发送数据。

(6) 错误检测功能:错误通知功能·错误恢复功能 所有的单元都可以检测错误(错误检测功能)。 检测出错误的单元会立即同时通知其他所有单元(错误通知功能)。 正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送 此消息直到成功发送为止(错误恢复功能)。

(7) 故障封闭: CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部 故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上 隔离出去。

(8) 连接:CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。 

ISO 标准化的 CAN 协议

CAN 协议经 ISO 标准化后有 ISO11898 标准和 ISO11519-2 标准两种。ISO11898 和 ISO11519-2 标准对于数据 链路层的定义相同,但物理层不同。

(1) 关于 ISO11898 ISO11898 是通信速度为 125kbps-1Mbps 的 CAN 高速通信标准。 目前,ISO11898 追加新规约后,成为 ISO11898-1 新标准。

(2) 关于 ISO11519 ISO11519 是通信速度为 125kbps 以下的 CAN 低速通信标准。 ISO11519-2 是 ISO11519-1 追加新规约后的版本。

 CAN 收发器根据两根总线(CAN_High 和 CAN_Low)的电位差来判断总线电平。 总线电平分为显性电平和隐性电平两种。总线必须处于两种电平之一。总线上执行逻辑上的线“与”时, 显性电平为“0”,隐性电平为“1”。

 以TJA1050收发器芯片数据手册为例:

         TJA1050 采用的是ISO11898标准, 总线电平=CAN_H的电压-CAN_L的电压,由数据手册可以看出,当电平在-1v-0.5v之间是隐性,电平在0.9-5v之间是显性。 显性电平对应逻辑0=总线电平为2V左右 隐性电平对应逻辑1=总线电平为0V。 显性电平具有优先权,只要有一个单元输出显性电平,总线上即为显性电平。 隐形电平则具有包容的意味,只有所有的单元都输出隐性电平, 总线上才为隐性电平(显性电平比隐性电平更强)。 在CAN总线的起止端都有一个120Ω的终端电阻,来做阻抗匹配,以减少回波反射,增加总线通信的稳定性。

通信波特率:CAN总线是基于相同波特率通信的,在同一网络中,所有单元必须设定成统一的通信速度,否则就会输出错误信号妨碍整个网络的通信。因此在设备接入总线之前就要先知道总线波特率是多少。计算公式参考:波特率=(pclk1/((1+8+7)*9)) = 36Mhz/16/9 = 250Kbits

设置低速AHB时钟(PCLK1),APB1时钟 = HCLK/2 = 36MHZ(外部晶振8HMZ)

设置高速AHB时钟(PCLK2),APB2时钟 = HCLK = 72MHZ(外部晶振8HMZ)

因为CAN总线挂载在APB1时钟上,所以pclk1=36Mhz。

 CAN协议

CAN总线发送部分:

报文:CAN设备一次发送出去的完整数据信息

邮箱:用于发送报文的发送调度器

帧种类:不同用途的报文种类。有数据帧、遥控帧、错误帧、过载帧、帧间隔

帧格式:一个报文里包含的内容。

标识符(ID):CAN总线上的设备可以用此判断数据是不是发给自己的

其中邮箱集成在CAN控制器中,有3个邮箱,当向程序向CAN控制器发数据时,CAN会选择优级级最高的空邮箱放入数据,如果所有邮箱都满了,会使溢出标志位置1,需要等待有空邮箱,满邮箱把先后顺序排队发送数据,发送完成后会变成空邮箱。

帧种类:

我们都知道,USART串口收发的都是没有格式的单纯数据,如果想用USART做高级应用,那么需要自定义数据格式。而在CAN总线中的报文是由格式的。

 CAN中的所有设备都会接收报文,但标识符(ID)不符的报文会被过滤器删除

每种报文的格式都不相同, 数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有 11 个位的标识符(Identifier: 以下称 ID), 扩展格式有 29 个位的 ID。

数据帧或遥控帧报文格式:

 数据帧:

遥控帧:

数据帧和遥控帧的不同 : 遥控帧的 RTR 位为隐性位,没有数据段。没有数据段的数据帧和遥控帧可通过 RTR 位区别开来。

 优先级的决定:

在总线空闲态,最先开始发送消息的单元获得发送权。 多个单元同时开始发送时,各发送单元从仲裁段的第一位开始进行仲裁。连续输出显性电平最多的单元可继续发送。

 仲裁过程

 数据帧和遥控帧的仲裁过程:

具有相同 ID 的数据帧和遥控帧在总线上竞争时,仲裁段的最后一位(RTR)为显性位的数据帧具有优先权, 可继续发送

标准格式和扩展格式的仲裁过程:

 在STM32中bxCAN特点:

1、CAN接口兼容规范2.0A和2.0B主动模式

2、波特率(位速率)最高可达1Mb/S

3、接受和发送11位标识符的数据帧或29位标识符的扩展帧

4、具有3个发送邮箱

5、3级深度的2个接受FIFO,3级14个可调节过滤器

FIFO:即先入先出,此指的是有层级深度的接受邮箱。STM32F103系列单片机上有2个FIFO邮箱,每个FIFO有3层深度。 与过滤器匹配的报文会被放入FIFO邮箱。

 CAN接收有2个邮箱,FIFO0和FIFO1,每个邮箱有3层深度。 3层深度是指每个邮箱可以接收3个报文,但读取时只能读到最先收到的报文 报文处理完成后,再读取时则是下一个报文。

过滤器:可由硬件判断报文中的标识符,过滤掉标识符不匹配的报文。 STM32F103系列单片机中的CAN总线控制器提供了14个过滤器组。 过滤器是由硬件实现的,只有与过滤器匹配的报文才需要软件处理。

在接受数据的时候,第一个问题就是搞懂如何接受的———过滤。

 过滤器组中的模式设置分为32位模式下的标识符屏蔽和标识符列表,16位模式下的标识符屏蔽和标识符列表。在 16 位模式下,只不过把两个 32 位寄存器拆成了 4 个 16 位的而已,原理和 32 位模式下是一 样的。

标识符列表模式:(这里仅用8位数据举例,实际的过滤器为16位或32位的)

 这里所说的ID并不是发送数据帧里面的 ID,这两个没有什么关系的,这 里的 ID 是根据自己的实际需要设置的。

标识符屏蔽模式:(这里仅用8位数据举例,实际的过滤器为16位或32位的)

因此这里的屏蔽和 ID 共同配合完成过滤。

 过滤器根据下列优先级规则来确定:

1、位宽为32位的过滤器,优先级高于位宽为16位的过滤器

2、对于位宽相同的过滤器,标识符列表模式的优先级高于屏蔽位模式

3、位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高

过滤器初始化函数:

u8 CAN_FilterConfiguration(viod){

	//设置过滤器
    CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
    CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;   //屏蔽位模式
    CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;  //32位宽 
    CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;    //32位ID
    CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
    CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;//屏蔽值都为0,代表任何数据都可以通过过滤器
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0
    CAN_FilterInit(&CAN_FilterInitStructure);           //滤波器初始化
}

发送和接收函数:


typedef struct
{
uint32_t StdId; //标准帧 ID,如果您要发送扩展帧。可以不管它
uint32_t ExtId; //扩展帧 ID,如果您要发送标准帧。可以不管它
uint8_t IDE; //您是想发送标准帧还是扩展帧?
uint8_t RTR; //您是想发送数据帧还是远程帧?
uint8_t DLC; // 您想发送数据的长度。
uint8_t Data[8]; //您想要发送的数据。
} CanTxMsg;

typedef struct
{
uint32_t StdId;
uint32_t ExtId;
uint8_t IDE;
uint8_t RTR;
uint8_t DLC;
uint8_t Data[8];
uint8_t FMI;//FMI域
} CanRxMsg;

//CAN发送一组数据(固定格式:ID为0X12,标准帧,数据帧)   
//msg:数据指针,最大为8个字节,len:数据长度(最大为8) 
//返回值:0,成功; 其他,失败;
u8 CAN_Send_Msg(u8* msg,u8 len){   
    u8 mbox;
    u16 i=0;
    CanTxMsg TxMessage;
    TxMessage.StdId=0x12;           // 标准标识符 
    TxMessage.ExtId=0x00;           // 设置扩展标识符
    TxMessage.IDE=CAN_Id_Standard;  // 标准帧
    TxMessage.RTR=CAN_RTR_Data;     // 数据帧
    TxMessage.DLC=len;              // 要发送的数据长度
    for(i=0;i<len;i++)
    TxMessage.Data[i]=msg[i];       //写入数据              
    mbox= CAN_Transmit(CAN1,&TxMessage);   
    i=0; 
    while((CAN_TransmitStatus(CAN1,mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待发送结束
    if(i>=0XFFF)return 1;
    return 0;    
}

//can口接收数据查询
//buf:数据缓存区;     
//返回值:0,无数据被收到,其他,接收的数据长度;
u8 CAN_Receive_Msg(u8 *buf){                  
    u32 i;
    CanRxMsg RxMessage;
    if(CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;//没有接收到数据,直接退出 
    CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);//读取数据 
    for(i=0;i<8;i++) //把8个数据放入参数数组
    buf[i]=RxMessage.Data[i];  
    return RxMessage.DLC;  //返回数据数量 
}

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值