4. CAN协议详解:数据帧、远程帧、错误帧、过载帧结构,仲裁机制与位填充规则
各位同学,今天我们来啃一块硬骨头——CAN协议的核心帧结构。说实话,我刚入行那会儿,看着CAN总线上那些0101的波形,也是一头雾水。但后来我发现,只要把四种帧结构搞明白,CAN总线基本就通了八成。
CAN总线上一共就四种帧:数据帧、远程帧、错误帧、过载帧。咱们一个一个来拆解。
4.1 数据帧——最常用的那个
数据帧,说白了就是“谁有话要说,就发一包数据出去”。我做过一个项目,车上十几个ECU,大部分时间都在发数据帧。数据帧的结构,我习惯把它分成七段:
| 段名称 | 位数 | 说明 |
|---|---|---|
| 帧起始(SOF) | 1 bit | 显性电平,同步信号 |
| 仲裁段 | 12或32 bit | ID + RTR + IDE + r0 |
| 控制段 | 6 bit | DLC + 保留位 |
| 数据段 | 0~64 bit | 实际数据内容 |
| CRC段 | 16 bit | CRC校验 + 界定符 |
| ACK段 | 2 bit | 应答槽 + 界定符 |
| 帧结束(EOF) | 7 bit | 隐性电平 |
嗯,这里要注意:标准帧和扩展帧的区别就在仲裁段。标准帧ID是11位,扩展帧是29位。我个人习惯,能用标准帧就别用扩展帧,省带宽。但有些项目非要29位ID,那就得硬着头皮上。
4.2 远程帧——只问不拿
远程帧很有意思。它就像你对着对讲机喊:“谁有数据?发给我!”但自己不带数据。远程帧的结构和数据帧几乎一样,唯一的区别是RTR位:数据帧的RTR是显性(0),远程帧的RTR是隐性(1)。
关键点:远程帧没有数据段。DLC字段表示请求的数据长度,但实际不发数据。
我曾经踩过一个坑:某个ECU发了远程帧请求车速数据,结果另一个ECU没响应。查了半天,发现是DLC对不上。你请求8字节,但对方只发4字节,那就对不上了。所以,DLC一定要约定好。
4.3 错误帧——总线上的警报器
错误帧,说白了就是“有人发现数据错了,赶紧喊停”。错误帧由两部分组成:
- 错误标志:6个连续的显性位(主动错误)或6个连续的隐性位(被动错误)
- 错误界定符:8个连续的隐性位
这里有个细节:主动错误节点会发送6个显性位,这会把总线上的其他节点也拉进错误状态。被动错误节点只能发6个隐性位,不会干扰总线。我遇到过一台ECU频繁进入被动错误状态,结果总线上一堆错误帧,整个网络都快瘫痪了。后来发现是它的晶振漂移了,导致位时序不对。
避坑指南:我曾经调试过一个项目,错误帧满天飞。用示波器一看,发现是终端电阻没焊好。CAN总线两端必须各有一个120Ω电阻,少一个都不行。
4.4 过载帧——我忙,别发
过载帧,说白了就是“我处理不过来了,等等再发”。它和错误帧结构很像,也是6个显性位+8个隐性位。但触发条件不同:
- 接收节点还没准备好接收下一帧
- 检测到位填充错误(这个后面讲)
过载帧在实际项目中不常见。我做了这么多年,也就碰到过两三次。一般是因为某个ECU的接收缓冲区太小,或者CPU负载太高。
4.5 仲裁机制——谁ID小谁先走
CAN总线的仲裁机制,我觉得是它最巧妙的设计。多个节点同时发送时,谁先抢到总线?答案是:ID最小的那个。
为什么?因为CAN总线是“线与”逻辑:显性(0)会覆盖隐性(1)。仲裁时,每个节点逐位发送自己的ID。如果某个节点发送了隐性位,但总线上是显性位,它就输了,乖乖退出发送。
个人经验:我习惯把高优先级消息(比如刹车、安全气囊)分配小ID,低优先级消息(比如车窗、空调)分配大ID。这样紧急消息总能抢到总线。
举个例子:节点A的ID是0x100,节点B的ID是0x200。同时发送时,A的ID第一位是0,B的第一位是1。A的显性位把B的隐性位覆盖了,B检测到总线电平和自己发的不一致,就退出了。最后A成功发送。
4.6 位填充规则——防止同步丢失
位填充,说白了就是“连续5个相同位,就插一个相反位”。为什么要有这个规则?因为CAN节点靠电平跳变来同步时钟。如果连续太多相同的位,节点就会失去同步。
规则很简单:
- 发送方:连续发送5个相同位后,自动插入一个相反位
- 接收方:检测到5个相同位后,自动删除下一个位(填充位)
但要注意:CRC界定符、ACK界定符、EOF这些固定格式的段,不进行位填充。我刚开始做CAN驱动时,就因为这个踩过坑——自己写的位填充逻辑把EOF也给填充了,结果接收方一直报错。
位填充范围:从SOF到CRC段(包括CRC段的数据,但不包括CRC界定符)。
4.7 本章知识体系
下面这张图,是我自己画的CAN帧结构关系图。你看一眼,基本就全串起来了:
这张图把四种帧的关系、结构、仲裁和位填充都串起来了。你保存下来,以后调试CAN总线时拿出来对照着看,会很有帮助。
我的建议:初学者可以先从数据帧入手,把它的七段结构背下来。然后对比远程帧,记住RTR位的区别。错误帧和过载帧先了解触发条件,遇到问题再回头查。
好了,CAN协议的帧结构就讲到这里。下一章我们聊聊CAN的位时序和同步机制,那个更烧脑,但搞懂了就能自己调波特率了。
可可精品资料库