CAN帧结构:数据帧、远程帧、错误帧、过载帧、帧间隔
各位同学,咱们今天聊聊CAN总线上的五种帧结构。说实话,我刚接触CAN协议时,也被这五种帧搞得有点晕。但后来我发现,只要搞懂了它们各自出现的场景,其实没那么复杂。
CAN总线上的通信,说白了就是靠这五种帧来完成的。它们分别是:数据帧、远程帧、错误帧、过载帧和帧间隔。咱们一个一个来拆解。
2.1 数据帧(Data Frame)
数据帧是最常用的帧类型。它负责把数据从一个节点发送到另一个节点。我个人习惯把数据帧想象成一个快递包裹——有收件地址、有内容、还有校验码。
数据帧分为两种格式:标准帧(11位ID)和扩展帧(29位ID)。它们的结构对比如下:
| 字段 | 标准帧 | 扩展帧 |
|---|---|---|
| SOF(帧起始) | 1位显性位 | 1位显性位 |
| 仲裁场 | 11位ID + RTR + IDE + r0 | 29位ID + SRR + IDE + RTR + r1 + r0 |
| 控制场 | DLC(4位) | DLC(4位) |
| 数据场 | 0~8字节 | 0~8字节 |
| CRC场 | 15位CRC + 1位CRC界定符 | 15位CRC + 1位CRC界定符 |
| ACK场 | 1位ACK槽 + 1位ACK界定符 | 1位ACK槽 + 1位ACK界定符 |
| EOF(帧结束) | 7位隐性位 | 7位隐性位 |
这里有个关键点:RTR位。数据帧的RTR位是显性(0),而远程帧的RTR位是隐性(1)。这是区分数据帧和远程帧的唯一标志。
2.2 远程帧(Remote Frame)
远程帧的作用是请求数据。说白了,就是一个节点对另一个节点说:“嘿,把你那个ID的数据发给我看看。”
远程帧的结构和数据帧几乎一样,唯一的区别就是RTR位为隐性(1),而且没有数据场。嗯,这里要注意:远程帧的DLC字段表示请求的数据长度,但实际不发送数据字节。
举个例子:
// 标准远程帧示例
// ID = 0x123, DLC = 8, RTR = 1
// 发送节点请求ID为0x123的节点发送8字节数据
// 标准数据帧示例(响应)
// ID = 0x123, DLC = 8, RTR = 0
// 数据 = 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
2.3 错误帧(Error Frame)
错误帧是CAN总线上的“报警器”。当节点检测到总线错误时,就会主动发送错误帧。错误帧由两部分组成:
- 错误标志(Error Flag):6个连续显性位(主动错误)或6个连续隐性位(被动错误)
- 错误界定符(Error Delimiter):8个连续隐性位
错误帧的触发条件有五种:
- 位错误:发送节点监控总线,发现实际电平与发送电平不一致
- 填充错误:连续5个相同电平后没有插入填充位
- CRC错误:接收节点计算的CRC与发送的CRC不匹配
- 形式错误:固定格式的位段出现非法电平
- ACK错误:发送节点在ACK槽没有收到显性位
关键概念:主动错误 vs 被动错误
每个CAN节点都有一个错误计数器。当错误计数超过127时,节点从主动错误状态变为被动错误状态。主动错误节点发送6个显性位,被动错误节点发送6个隐性位。说白了,主动错误能“打断”总线,被动错误只能“小声嘀咕”。
2.4 过载帧(Overload Frame)
过载帧的作用是告诉总线:“我忙不过来了,慢点发。”它和错误帧结构类似,但触发条件不同。
过载帧的触发条件:
- 接收节点内部处理不过来,需要延迟下一个数据帧或远程帧
- 在帧间隔的间歇场检测到显性位(非法情况)
过载帧的结构:
- 过载标志(Overload Flag):6个连续显性位
- 过载界定符(Overload Delimiter):8个连续隐性位
2.5 帧间隔(Interframe Space)
帧间隔不是一种独立的帧,而是帧与帧之间的“休息时间”。它确保总线上的节点有足够的时间准备接收下一帧。
帧间隔由三部分组成:
| 字段 | 长度 | 说明 |
|---|---|---|
| 间歇场(Intermission) | 3个隐性位 | 所有节点必须等待这3位才能开始发送 |
| 总线空闲(Bus Idle) | 任意长度隐性位 | 总线空闲,节点可以开始发送 |
| 暂停场(Suspend Transmission) | 8个隐性位 | 仅被动错误节点需要,主动错误节点跳过 |
这里有个细节:被动错误节点在发送完一帧后,必须额外等待8个隐性位的暂停场才能继续发送。这是为了防止故障节点“霸占”总线。
2.6 五种帧的关系与状态机
为了让大家更直观地理解这五种帧在总线上的流转关系,我画了一张图:
2.7 实战要点总结
好了,咱们把五种帧的核心要点总结一下:
数据帧:最常用,带数据内容,RTR=0
远程帧:请求数据,无数据场,RTR=1
错误帧:总线错误时触发,6+8位结构
过载帧:节点忙时触发,6+8位结构
帧间隔:帧与帧之间的休息时间,3+8位
在NMT从站节点开发中,你最常打交道的是数据帧和远程帧。错误帧和过载帧更多是调试时用来定位问题的。帧间隔则是你写驱动时必须考虑的时间参数。