2、CAN协议详解:CAN数据帧结构、CAN远程帧、CAN错误帧、CAN过载帧
CAN协议,说白了就是一套让多个节点在一条总线上有序说话的规则。我刚开始接触CAN时,觉得帧结构挺复杂,但后来发现,只要搞懂四种帧——数据帧、远程帧、错误帧、过载帧,整个协议就通了八成。
咱们先看一张总览图,把这四种帧的关系理清楚。
2.1 数据帧——最常用的帧
数据帧就是用来发送数据的。一个节点把数据打包成帧,广播到总线上,其他节点根据ID决定要不要接收。我做过一个项目,车上十几个ECU全靠数据帧交换信息,谁发什么ID,提前约定好。
数据帧的结构,我习惯分成七段来看:
| 段名称 | 位数(标准帧) | 说明 |
|---|---|---|
| 帧起始 | 1 bit | 显性电平,同步所有节点 |
| 仲裁段 | 12 bits | 包含11位ID + RTR位,决定优先级 |
| 控制段 | 6 bits | IDE位、保留位、DLC(数据长度码) |
| 数据段 | 0~64 bits | 实际数据,最多8字节 |
| CRC段 | 16 bits | 15位CRC + 1位CRC界定符 |
| ACK段 | 2 bits | 接收节点回应,确认收到 |
| 帧结束 | 7 bits | 隐性电平,表示帧结束 |
关键点:数据段最多8字节。为什么是8?早期设计时,考虑到汽车控制信号的实时性要求,8字节足够传递大部分传感器和执行器数据。我见过有人非要把大包拆成多个CAN帧发,其实没必要——超过8字节就该考虑用CAN FD了。
标准帧和扩展帧的区别,主要在仲裁段。标准帧11位ID,扩展帧29位ID。我个人的习惯是:能用标准帧就别用扩展帧,因为标准帧的仲裁效率更高,总线利用率也更好。
2.2 远程帧——问别人要数据
远程帧,说白了就是“请求帧”。一个节点发远程帧,告诉另一个节点:“把你的数据发给我。” 远程帧的结构和数据帧几乎一样,唯一的区别是RTR位为隐性(1)。
我记得有一次调试一个电机控制器,它总是不响应我的远程帧请求。查了半天,发现是对方固件里把远程帧处理关掉了。嗯,这里要注意:不是所有CAN节点都会处理远程帧,很多设备只认数据帧。
实战建议:远程帧在实际工程中用得不多。我建议你尽量用数据帧主动上报,而不是靠远程帧去轮询。原因很简单:远程帧会增加总线负载,而且响应时间不可控。
2.3 错误帧——总线出了问题怎么办
错误帧是CAN控制器硬件自动发的,不需要软件干预。一旦节点检测到总线错误,就会立刻发送错误帧,通知所有节点“刚才那帧有问题,别用了”。
错误帧由两部分组成:
- 错误标志:6个连续显性位(主动错误)或6个连续隐性位(被动错误)
- 错误界定符:8个连续隐性位
CAN协议定义了五种错误类型:
| 错误类型 | 触发条件 | 我遇到过的案例 |
|---|---|---|
| 位错误 | 发送节点监控到总线电平与发送不一致 | 有一次总线短路,发送显性位却读到隐性 |
| 填充错误 | 连续6个相同电平,违反位填充规则 | 干扰导致位翻转,触发填充错误 |
| CRC错误 | 接收节点计算的CRC与发送的不一致 | 波特率不匹配时最常见 |
| 形式错误 | 固定格式位(如界定符)电平错误 | 硬件时序问题导致 |
| 应答错误 | 发送节点没收到ACK显性位 | 总线上只有发送节点自己 |
避坑指南:我曾经在产线上遇到一个批量问题——某批ECU频繁报CRC错误。查到最后发现是晶振精度不够,导致位时序偏差累积。所以,CAN节点的时钟精度一定要控制在1%以内,最好用0.5%的晶振。
2.4 过载帧——我忙不过来了
过载帧,是节点告诉总线“我处理不过来了,慢一点”。它和错误帧长得有点像,但触发原因完全不同。
过载帧的结构:
- 过载标志:6个连续显性位
- 过载界定符:8个连续隐性位
触发过载帧的两种情况:
- 接收节点内部条件不成熟,比如接收缓冲区满了
- 帧间隔期间检测到显性位(这属于总线干扰)
说实话,我在实际项目中很少见到过载帧。现在的CAN控制器缓冲区都比较大,加上合理的软件设计,一般不会触发过载。如果你在调试时频繁看到过载帧,先检查一下接收中断处理是不是太慢了。
2.5 四种帧的对比总结
最后,我用一张表把这四种帧的核心差异列出来,方便你对照:
| 帧类型 | 触发方式 | 数据段 | RTR位 | 用途 |
|---|---|---|---|---|
| 数据帧 | 软件主动发送 | 有(0~8字节) | 显性(0) | 传输数据 |
| 远程帧 | 软件主动发送 | 无 | 隐性(1) | 请求数据 |
| 错误帧 | 硬件自动触发 | 无 | — | 通知总线错误 |
| 过载帧 | 硬件自动触发 | 无 | — | 请求延迟发送 |
你想想看,这四种帧其实覆盖了CAN总线通信的所有场景:正常发数据用数据帧,要数据用远程帧,出错了硬件自动发错误帧,忙不过来就发过载帧。搞懂这些,CAN协议的基础就算打牢了。