CAN 总线协议
本文主要介绍 CAN 总线协议的基本概念,目的是让大家对 CAN 总线协议有一个大概的认知,具体的协议规范将在后续章节介绍。
参考模型
所有标准的工业通信系统都必须符合国际标准化组织(ISO)所定义的 OSI(开放系统互联模型)开放协议标准。下图是在 OSI 参考模型下描述的 CANopen 通信系统。
实际上,由于 CAN-bus 的国际标准只对物理层和数据链路层制定了规范,并没有定义应用层的规范。因此,CAN 用户要么采用自己定义的应用层协议,要么采用通用的应用层协议。显然,后者是更好的选择,能够使产品更加通用和国际化。
CANopen 协议就是在现场总线 CAN-bus 之上定义的一套应用层协议,其核心是对象字典和多种通信方式,所有 CANopen 功能均被映射到一个或多个 CAN 报文。
物理层
在 CAN 网络中,总线电平分为两种 —— 显性电平 和 隐性电平。显性电平覆盖隐性电平。也就是说,当来自同一 CAN 网络的各个不同总线设备同时发送显性电平和隐性电平时,总线上只会出现显性电平;仅当网络上的所有总线设备同时发送隐性电平时,总线上才会出现隐性电平。
CAN 规范中定义,隐性电平的逻辑值为 1,显性电平的逻辑值为 0。
报文格式
为了识别 CAN 总线上的传输信息,必须通过一种固定的格式来打包(封装)这些信息。通常,使用“帧”(Frame)来描述这些格式。
在 CAN 总线上传输的帧一共有四种类型 —— 数据帧、远程帧、错误帧、超载帧。每一个帧都由多个称为“域”(Field)的信息区构成,而每一个域又包含一个或多个位。
数据帧
下图展示了 CAN 标准格式数据帧的组成。
数据帧由7段构成
起始段 | 仲裁段 | 控制段 | 数据段 | CRC段 | ACK段 | 帧结束 | |
---|---|---|---|---|---|---|---|
bit | 1 | 12 | 6 | 0-64 | 16 | 2 | 7 |
各个域的说明如下:
- 起始段:长度固定为 1 bit,逻辑 0;
- 仲裁段:前 11 bit 为帧 ID,后 1 bit 为 RTR 标志;
- 控制段:前 2 bit 规定为 0,后 4 bit 为数据段的 Byte 长度;
- 数据段:长度可变,0~8 Byte;
CRC段、ACK段、帧结束对于软件工程师来说可以不关注,比较重要的是理解仲裁段、控制段和数据段的含义。另外,没有数据段的数据帧一般用作心跳。
远程帧
远程帧也称为遥控帧,它的作用是向其他单元请求数据。比如设备 A 希望设备 B 向自己发送数据,那么设备 A 就向总线发送一个带有设备 B 的帧 ID 的遥控帧,设备 B 就会将数据发送的总线上。
需要注意,CAN 总线协议是广播的。远程帧也包含帧 ID,当 CAN 总线上有远程帧与数据帧同时要发送时,也要根据 ID 的优先级仲裁,如果 ID 相同则数据帧具有更高优先级。
错误帧
顾名思义,错误帧是在检测到错误时发送到 CAN 总线上的帧,分为主动错误帧和被动错误帧两类。
每一个 CAN 总线芯片都会有错误计数器,初值为 0。假设设备 A 总是发送错误。A 发送一个数据帧后,发现有错误(这个发现错误的功能也是硬件实现的,应该是 A 发送数据的同时,也在校验总线上的数据),则 A 会将自己的错误计数器加 8,并发送一个主动错误帧,其他设备如果接收到这个主动错误帧,会将自己的计数器加 1;当 A 的计数器达到 127 时,A 将改为发送被动错误帧,并依然给计数器加 8,但不再发送数据帧;最后当 A 的计数器达到 256 时,A 将不再工作。
以上的描述其实没有解释主动错误帧和被动错误帧在功能上有什么区别,只是描述了以下发送时机,CAN 规范协议对错误帧的规定十分复杂。
超载帧
超载帧也称为过载帧,通常由尚未处理完上一帧消息的 CAN 控制器发出,可以用于延迟网络中其他设备发送下一条帧消息。
不过,现在市场上主流的 CAN 控制器都已经不再主动发送过载帧,但仍会遵循 CAN 规范的要求,对过载帧作出延迟发送的反应。