2、CAN协议基础:CAN数据帧结构、CAN远程帧、CAN错误帧、CAN过载帧、帧间隔
好,咱们进入正题。CAN协议里最核心的,就是这几种帧。说白了,CAN总线上的所有通信,都是靠这些帧来完成的。我刚开始接触CAN的时候,也被这些帧的名字搞得有点晕。但别怕,咱们一个一个拆开看。
2.1 CAN数据帧:最常用的“快递包裹”
数据帧,就是用来发送数据的。你可以把它想象成一个快递包裹。这个包裹有固定的格式,谁寄的、寄给谁、里面装了什么,都得写清楚。
数据帧有两种格式:标准帧和扩展帧。区别就在于ID的长度。标准帧ID是11位,扩展帧ID是29位。我个人习惯,如果项目里节点不多,用标准帧就够了,简单高效。
一个完整的数据帧,由以下几个部分组成:
- 帧起始(SOF):一个显性位(0)。告诉总线上的所有节点:“我要开始发数据了!”
- 仲裁场:包含ID和RTR位。ID决定了消息的优先级。ID越小,优先级越高。RTR位用来区分是数据帧还是远程帧。
- 控制场:包含IDE位和DLC。IDE位用来区分是标准帧还是扩展帧。DLC表示数据场有多少个字节(0-8)。
- 数据场:0到8个字节的数据。这就是你要发送的真正内容。
- CRC场:循环冗余校验。用来检查数据在传输过程中有没有出错。
- ACK场:应答场。接收节点如果正确收到了数据,就会在这里回一个显性位,告诉发送方:“我收到了!”
- 帧结束(EOF):7个隐性位(1)。表示这个帧结束了。
重点:仲裁场是CAN总线实现“无损位仲裁”的关键。多个节点同时发送时,ID最小的那个会赢得仲裁,继续发送。其他节点自动转为接收。这个机制非常巧妙,我当年第一次理解时,觉得设计者真是个天才。
我的经验:在设计系统时,一定要把紧急消息的ID设小一点。比如刹车指令的ID设为0x001,车窗指令设为0x100。这样刹车指令永远优先。我曾经在一个项目中,把两个关键消息的ID设反了,结果调试时发现优先级总是不对,查了半天才找到原因。
2.2 CAN远程帧:请求数据的“挂号信”
远程帧,说白了就是“请求数据”。一个节点如果想从另一个节点获取数据,就可以发一个远程帧。远程帧的结构和数据帧几乎一样,唯一的区别是RTR位是隐性位(1)。
远程帧没有数据场。它的DLC字段表示它希望接收多少字节的数据。比如,节点A发一个远程帧,ID=0x100,DLC=4。那么节点B收到后,就知道节点A想要ID为0x100的4个字节数据。节点B就会发一个数据帧,ID=0x100,数据场里放4个字节。
注意:远程帧的ID和数据帧的ID是共享的。也就是说,你不能同时用同一个ID既发数据帧又发远程帧。否则会冲突。我曾经见过一个新手,把远程帧和数据帧的ID设成一样,结果总线上一片混乱。
2.3 CAN错误帧:总线的“警报器”
错误帧,是CAN总线自我保护的机制。当任何一个节点检测到错误时,就会发送错误帧。错误帧由两部分组成:错误标志和错误界定符。
- 错误标志:6个连续的显性位(0)。这会破坏当前正在传输的帧,让所有节点都知道出错了。
- 错误界定符:8个连续的隐性位(1)。用来结束错误帧。
CAN协议定义了五种错误类型:
| 错误类型 | 说明 |
|---|---|
| 位错误 | 发送节点发送的位和总线上监测到的位不一致。 |
| 填充错误 | 连续出现了6个相同电平的位(违反位填充规则)。 |
| CRC错误 | 接收节点计算的CRC和发送节点的CRC不一致。 |
| 形式错误 | 帧的固定格式部分出现错误(比如EOF不是7个隐性位)。 |
| 应答错误 | 发送节点没有收到ACK应答。 |
避坑指南:我曾经在一个项目中,发现总线偶尔会莫名其妙地报错。查了很久,最后发现是一个节点的晶振频率偏差太大,导致位时序不对。嗯,这里要注意,CAN总线的位时序对时钟精度要求很高。如果时钟不准,很容易出现位错误。
2.4 CAN过载帧:总线的“稍等一下”
过载帧,用来告诉发送节点:“我忙不过来了,你慢点发。” 它和错误帧的结构很像,也是由过载标志和过载界定符组成。
- 过载标志:6个连续的显性位(0)。
- 过载界定符:8个连续的隐性位(1)。
过载帧通常在两种情况下产生:
- 接收节点内部条件不满足,无法处理下一个数据。
- 在帧间隔期间,检测到显性位(这被视为一个过载条件)。
我的建议:过载帧在实际项目中用得不多。因为大多数MCU的CAN控制器都有硬件FIFO,可以缓存多个消息。除非你的系统负载极高,否则很少需要主动发送过载帧。但了解它还是有必要的,万一哪天遇到了,不至于抓瞎。
2.5 帧间隔:总线的“休息时间”
帧间隔,就是两个帧之间的空闲时间。它用来让总线上的节点有时间准备接收下一个帧。帧间隔由间歇场和总线空闲组成。
- 间歇场:3个隐性位(1)。
- 总线空闲:任意长度的隐性位(1)。只要总线是空闲的,节点就可以开始发送。
这里有个细节:对于被动错误节点,帧间隔还会多一个挂起传输场(8个隐性位)。这是为了让主动错误节点有机会先发送。
总结一下:数据帧是主力,远程帧是辅助,错误帧是保安,过载帧是协调员,帧间隔是休息时间。这五种帧共同构成了CAN总线的通信基础。你想想看,一个总线协议能把这些都考虑进去,是不是很厉害?
好了,这一章的内容就到这里。下一章我们会深入CAN的位时序和同步机制,那才是真正考验功底的地方。做好准备!