3. CAN数据链路层:CAN帧的种类与帧格式
数据链路层,说白了就是CAN通信的“交通规则”。它规定了数据怎么打包、怎么发送、怎么避免冲突。我刚开始接触CAN时,总觉得这层太抽象,后来调了几次总线,才明白这些帧类型就是日常打交道的“基本单元”。
3.1 CAN帧的四种类型
CAN总线上跑的消息,一共就四种帧。你想想看,就像马路上的车,有载货的、有空跑的、有出事故的、还有临时管控的。CAN帧也是这个道理。
| 帧类型 | 英文名 | 主要用途 | 谁发起的 |
|---|---|---|---|
| 数据帧 | Data Frame | 携带实际数据从发送器到接收器 | 发送节点 |
| 远程帧 | Remote Frame | 请求某个ID的数据,自己不携带数据 | 接收节点 |
| 错误帧 | Error Frame | 检测到总线错误时主动报告 | 任何节点 |
| 过载帧 | Overload Frame | 接收节点忙不过来,请求延迟发送 | 接收节点 |
核心要点:数据帧和远程帧是“正常通信”用的,错误帧和过载帧是“异常处理”用的。调试CAN总线时,80%的时间你都在看数据帧和错误帧。
3.2 数据帧(Data Frame)—— 最常用的帧
数据帧就是“拉货的车”。它负责把传感器数据、控制指令从一个节点传到另一个节点。我个人习惯把数据帧的结构拆成七段来记,这样分析报文时一眼就能看出问题。
3.2.1 数据帧的七段结构
- 帧起始(SOF):1个显性位,告诉总线“我要开始发了”。
- 仲裁段:包含ID和RTR位,决定谁能抢到总线。
- 控制段:包含IDE位、保留位和DLC(数据长度码)。
- 数据段:0~8字节的实际数据,这才是我们真正关心的。
- CRC段:15位CRC校验码+1位CRC界定符,保证数据没被干扰。
- ACK段:接收节点回应“我收到了”。
- 帧结束(EOF):7个隐性位,表示帧结束。
我的经验:调试时我最先看DLC(数据长度码)。如果DLC是8但实际只用了2个字节,说明设计时预留了空间。如果DLC是0但数据段还有值,那八成是协议栈配置错了——我曾经被这个问题坑过一整天。
3.3 远程帧(Remote Frame)—— 请求数据的“空车”
远程帧很有意思,它自己不拉货,只是告诉某个节点:“把你的数据发给我”。它的结构和数据帧几乎一样,唯一的区别是RTR位为隐性(1)。
为什么会这样?因为远程帧不需要数据段,所以DLC通常为0。但注意,DLC可以不为0,只是数据段不包含有效数据。
避坑指南:我曾经在一个项目中,远程帧的DLC写成了8,结果接收节点以为要发8字节数据,实际只发了2字节,导致CRC校验一直不过。后来查了三天才发现是DLC没对齐。记住:远程帧的DLC必须与对应数据帧的DLC一致。
3.4 错误帧(Error Frame)—— 总线的“报警器”
错误帧是CAN总线自我保护的机制。任何节点检测到错误,都会立即发送错误帧。它由两部分组成:
- 错误标志:6个连续相同位(显性或隐性,取决于错误类型)。
- 错误界定符:8个隐性位。
错误帧一出现,所有节点都会停止当前发送,重新仲裁。嗯,这里要注意:频繁的错误帧说明总线有问题,可能是终端电阻不对、波特率不匹配、或者线缆干扰太大。
实战判断:用CAN分析仪抓包时,如果看到大量错误帧,先检查终端电阻(标准是120Ω,两端各一个)。我遇到过好几次,都是因为终端电阻虚焊导致总线反射,错误帧满天飞。
3.5 过载帧(Overload Frame)—— 接收节点的“缓一缓”
过载帧用得比较少,但关键时刻能救命。当接收节点处理不过来时,它会发送过载帧,告诉发送节点“我忙,你等会儿再发”。
过载帧的结构和错误帧很像:6个显性位+8个隐性位。区别在于,过载帧只在帧间空间(Interframe Space)发送,不会打断正在进行的帧传输。
3.6 标准帧与扩展帧
CAN 2.0规范定义了两种帧格式:标准帧和扩展帧。区别就在ID长度上。
| 对比项 | 标准帧 | 扩展帧 |
|---|---|---|
| ID长度 | 11位 | 29位 |
| 可用的ID数量 | 2^11 = 2048个 | 2^29 = 5.36亿个 |
| IDE位 | 显性(0) | 隐性(1) |
| 帧长度 | 较短,效率高 | 较长,灵活性高 |
| 典型应用 | J1939、CANopen | 自定义协议、多节点系统 |
你想想看,11位ID只有2048个,在乘用车里勉强够用。但到了工程机械、船舶这些动辄上百个节点的系统,29位ID就很有必要了。我做过一个农机项目,用了扩展帧,每个ECU分配一个独立ID范围,调试时一眼就能看出是哪个节点在发数据。
3.7 知识体系总览
下面这张图把CAN帧的种类和格式串起来了。我建议你把它存下来,以后分析报文时对照着看。
个人建议:刚开始学CAN时,先把数据帧的标准格式吃透。11位ID、8字节数据、CRC校验——这三个概念搞明白了,后面扩展帧、远程帧都是锦上添花。我当年就是先拿一个标准帧的报文反复拆解,一周后看其他帧就豁然开朗了。