第1章:CAN数据帧详解
各位同学,今天咱们来啃一块硬骨头——CAN数据帧。说实话,我当年刚接触CAN协议时,也被这些帧结构、仲裁机制搞得晕头转向。但后来在几个工业现场项目中摸爬滚打,才真正理解了设计者的良苦用心。
先给大家看一张总览图,把本章的知识脉络理清楚:
1.1 标准帧与扩展帧
CAN总线上的数据帧,说白了就两种格式:标准帧和扩展帧。区别在哪?就在ID长度上。
标准帧的ID是11位,可以表示0x000到0x7FF,一共2048个ID。够用吗?早期CAN网络节点少,确实够。但后来汽车电子越来越复杂,一个车上几十个ECU,11位ID就不够分了。
扩展帧的ID是29位,范围0x00000000到0x1FFFFFFF,将近5.4亿个ID。我参与过一个工程机械项目,整机上有40多个CAN节点,用的就是扩展帧。说实话,29位ID我们用到项目结束也没用完。
关键区别对照表:
| 特性 | 标准帧 | 扩展帧 |
|---|---|---|
| ID长度 | 11位 | 29位 |
| ID范围 | 0x000 ~ 0x7FF | 0x00000000 ~ 0x1FFFFFFF |
| 帧长度 | 最短47位 | 最短67位 |
| 仲裁优先级 | 相同ID下优先 | 标准帧优先于扩展帧 |
| 应用场景 | 简单系统、节点少 | 复杂系统、节点多 |
实战经验:我个人习惯在项目初期就确定用标准帧还是扩展帧。如果系统节点超过10个,或者未来有扩展需求,直接上扩展帧。改协议比改硬件痛苦多了——我吃过这个亏。
1.2 数据帧结构
一个完整的CAN数据帧,由7个段组成。咱们一个一个来看:
- 帧起始 (SOF):1个显性位,告诉总线上所有节点"我要发数据了"。
- 仲裁段:包含ID和RTR位。标准帧11位ID,扩展帧29位ID。RTR位决定是数据帧还是远程帧。
- 控制段:6位。包含IDE位、保留位和DLC(数据长度码)。DLC告诉接收方数据段有多长。
- 数据段:0~8字节。这就是真正要传输的数据。注意,CAN一次最多传8字节。
- CRC段:15位CRC校验码+1位CRC界定符。用来检查数据有没有传错。
- ACK段:2位。发送方发隐性位,接收方如果正确接收就拉成显性位。这就是"应答"。
- 帧结束 (EOF):7个隐性位。告诉总线"我发完了"。
你想想看,一个数据帧里,真正传数据的只有数据段那0~8个字节。其他段都是"开销"。但正是这些开销,保证了CAN通信的可靠性。
注意:我曾经在调试一个电机控制器时,发现数据偶尔会丢包。查了两天,最后发现是DLC设置错了——我发了8字节数据,但DLC写的是4。接收方只读了4个字节,后面4个字节全丢了。这种低级错误,大家千万别犯。
1.3 仲裁机制
CAN总线是"多主"架构,也就是说,任何节点都可以随时往总线上发数据。那问题来了:如果两个节点同时发数据,冲突了怎么办?
这就是仲裁机制要解决的问题。说白了,就是"谁优先级高,谁先发"。
仲裁的规则很简单:
- 显性位(逻辑0)优先级高于隐性位(逻辑1)
- ID值越小,优先级越高
- 标准帧优先级高于扩展帧
- 数据帧优先级高于远程帧
具体怎么仲裁?每个节点在发送仲裁段时,会同时监听总线电平。如果自己发的是隐性位,但总线上是显性位,说明有更高优先级的节点在发数据。这时候,这个节点就自动退出发送,转为接收模式。
嗯,这里要注意:仲裁过程不会破坏数据。因为仲裁段只包含ID和RTR位,不包含实际数据。仲裁失败的节点,会在总线空闲后自动重发。
举个例子:
节点A发ID=0x123,节点B发ID=0x124。二进制分别是:
A: 0001 0010 0011
B: 0001 0010 0100
从高位开始逐位比较,到第10位时,A发0(显性),B发1(隐性)。B发现总线是显性,知道自己输了,乖乖退出发送。A继续发完。
避坑指南:我曾经在一个项目中,把两个关键节点的ID设成了0x100和0x101。结果0x100的节点总是抢到总线,0x101的节点经常发不出数据。后来我把0x101改成了0x200,问题解决了。记住:ID分配要留足间隔,别挤在一起。
1.4 位填充规则
位填充,是CAN协议里一个容易被忽视但非常重要的机制。它的作用是保证时钟同步。
规则很简单:发送方在连续发送5个相同电平的位之后,必须插入一个相反电平的位。接收方在收到5个相同电平的位之后,会自动删除后面那个位。
举个例子:如果数据是 11111 00000,经过位填充后变成 111110 000001。注意,填充位是自动插入的,接收方会自动删除。
为什么要这么做?因为CAN总线没有单独的时钟线,接收方靠检测电平跳变来同步时钟。如果长时间没有跳变,接收方的时钟就会漂移,导致采样错误。
重要提醒:位填充规则适用于SOF到CRC段之间的所有位。EOF段和ACK段不参与位填充。另外,如果连续出现6个相同电平,那就是"填充错误",接收方会发送错误帧。
我记得有一次调试CAN总线,发现通信时好时坏。用示波器一看,波形上有连续6个隐性位。查了半天,发现是某个节点的晶振频率偏了,导致发送的位时间不准,触发了填充错误。换了晶振就好了。
位填充的影响:
位填充会导致实际发送的位数比理论值多。最坏情况下,每5位就要插入1位填充位,数据量增加20%。所以在计算总线负载率时,一定要把填充位算进去。我一般按20%的余量来估算。
好了,CAN数据帧的核心内容就这些。标准帧和扩展帧的区别、7段帧结构、仲裁机制、位填充规则,这四个知识点是理解CAN协议的基础。下一节咱们会讲Modbus协议,到时候再对比着看,你会发现很多有意思的东西。
公众号:蓝海资料掘金营,微信deep3321