第2章:CAN协议详解——数据帧、远程帧、错误帧、过载帧与帧间隔
大家好,我是老张。今天咱们来啃CAN协议里最核心的部分——五种帧结构。说实话,我刚入行那会儿,光看协议文档看得头大,后来在项目里亲手抓了几次波形,才真正搞明白。这一章,我就把当年踩过的坑和积累的经验,一股脑儿倒给你们。
2.1 数据帧:最常用的“快递包裹”
数据帧,说白了就是CAN总线上最常用的消息格式。它负责把数据从一个节点送到另一个节点。你想想看,就像寄快递,总得有收件地址、发件人、包裹内容吧?CAN数据帧也一样。
标准格式的数据帧长这样:
SOF + 11位ID + RTR + IDE + r0 + 4位DLC + 0~8字节数据 + 15位CRC + CRC分隔符 + ACK槽 + ACK分隔符 + EOF
嗯,这里要注意,扩展格式是29位ID,结构稍有不同。我个人习惯把标准帧叫“短地址”,扩展帧叫“长地址”。
关键字段解读:
- SOF(Start of Frame):一个显性位,告诉总线“我要发消息了”。
- ID(标识符):决定消息优先级。ID越小,优先级越高。我在项目中遇到过,两个节点同时发消息,ID小的那个总能抢到总线。
- RTR(Remote Transmission Request):数据帧里这位置0,远程帧里置1。
- DLC(Data Length Code):数据长度,0到8字节。别问我为什么是8,这是CAN协议定死的。
- 数据段:0~8字节,想传啥传啥。但要注意字节序,不同厂商可能不一样。
- CRC:15位校验码,加上1位分隔符。用来检测传输错误。
- ACK:接收节点如果正确收到,会在ACK槽里回一个显性位。发送节点会检查这个。
我的经验:调试时,我习惯先看ACK位。如果总线上没有ACK响应,八成是节点没收到或者ID没对上。我曾经花了一整天查一个bug,最后发现是CAN收发器的终端电阻没焊好。
2.2 远程帧:问别人要数据
远程帧,说白了就是“请求帧”。一个节点想从另一个节点拿数据,就发个远程帧过去。结构跟数据帧几乎一样,区别就两点:
- RTR位为1(隐性)
- 没有数据段
你可能会问:“没有数据段,那DLC干嘛用的?”问得好!DLC在这里表示你期望对方返回的数据长度。比如你发个远程帧,DLC=8,对方就知道你要8字节数据。
避坑指南:我曾经在项目里犯过一个低级错误——远程帧的ID设错了。结果对方节点根本没响应,总线上一片死寂。后来抓波形才发现,ID差了一个bit。记住,远程帧的ID必须和目标数据帧的ID完全一致。
2.3 错误帧:总线的“警报器”
错误帧,是CAN总线自我保护的机制。当节点检测到错误,就会立刻发错误帧,通知所有节点“刚才那包数据有问题,别用了”。
错误帧分两部分:
- 错误标志:6个连续显性位(主动错误)或6个连续隐性位(被动错误)
- 错误分隔符:8个隐性位
为什么会这样?因为CAN总线采用“错误主动”和“错误被动”两种状态。主动错误的节点可以破坏总线,被动错误的节点只能默默发隐性位。
错误类型有5种:
- 位错误:发送节点发现总线上的电平跟自己发的不一致。
- 填充错误:连续5个相同电平后,没看到填充位。
- CRC错误:接收节点算出来的CRC跟发过来的对不上。
- 格式错误:固定格式的位(比如CRC分隔符)不是隐性。
- ACK错误:发送节点没收到ACK响应。
我记得有一次,客户反馈说总线偶尔会“卡死”。我抓了一整天波形,发现是某个节点在不停发错误帧。最后查出来,那个节点的晶振频率偏了,导致位时序不对。嗯,硬件问题有时候就是这么隐蔽。
2.4 过载帧:总线说“我忙,等会儿”
过载帧,说白了就是“忙帧”。当接收节点来不及处理数据,或者总线出现某些异常条件,节点就会发过载帧,让发送节点等一等。
结构跟错误帧很像:
- 过载标志:6个显性位
- 过载分隔符:8个隐性位
过载帧和错误帧的区别在于:过载帧是“主动请求延迟”,错误帧是“被动报告问题”。你想想看,一个是你自己说“慢点”,另一个是系统报警“出错了”。
我的建议:如果总线上频繁出现过载帧,别急着怀疑协议栈。先看看接收节点的CPU负载是不是太高了,或者中断响应是不是太慢了。我曾经遇到过,一个节点用了个慢速的MCU,CAN中断处理不过来,结果过载帧满天飞。
2.5 帧间隔:总线的“休息时间”
帧间隔,就是两帧之间的空闲时间。CAN总线规定,每发完一帧,必须等3个隐性位才能发下一帧。这3个隐性位叫“间歇场”。
帧间隔的结构:
- 间歇场:3个隐性位
- 总线空闲:任意长度的隐性位(直到有节点开始发SOF)
这里有个细节:被动错误节点在间歇场之后,还要多等8个隐性位(叫“挂起传输”)。为什么?为了让主动错误节点有机会先抢到总线。
避坑指南:我曾经在写CAN驱动时,忽略了帧间隔的要求。结果两个节点连续发帧,中间没有间歇场,总线直接报错。后来查协议文档才发现,帧间隔是强制性的,不是可选的。
2.6 五种帧的对比总结
好了,咱们把五种帧放在一起对比一下:
| 帧类型 | 用途 | 数据段 | RTR位 | 触发条件 |
|---|---|---|---|---|
| 数据帧 | 发送数据 | 0~8字节 | 0(显性) | 节点主动发送 |
| 远程帧 | 请求数据 | 无 | 1(隐性) | 节点主动请求 |
| 错误帧 | 报告错误 | 无 | N/A | 检测到错误 |
| 过载帧 | 请求延迟 | 无 | N/A | 接收节点忙 |
| 帧间隔 | 帧间分隔 | 无 | N/A | 每帧结束后 |
你想想看,这五种帧配合起来,就构成了CAN总线完整的通信机制。数据帧和远程帧负责“干活”,错误帧和过载帧负责“异常处理”,帧间隔负责“节奏控制”。
核心要点:
- 数据帧和远程帧的ID必须一致才能配对
- 错误帧会破坏当前传输,所有节点都要丢弃数据
- 过载帧不会破坏数据,只是请求延迟
- 帧间隔是强制性的,不能省略
好了,这一章就到这里。下一章咱们聊聊CAN的位时序和同步机制,那可是理解CAN通信质量的关键。到时候我会分享一个我当年调试位时序的案例,保证让你印象深刻。
课后练习:用CAN分析仪抓一段总线数据,找出里面的数据帧、远程帧和错误帧。看看它们的ID、DLC和ACK位有什么规律。我当年就是这么学的,效果比看书好十倍。
公众号:蓝海资料掘金营,微信deep3321