第2章:CAN协议基础:CAN协议分层、CAN报文帧格式
各位工程师朋友,大家好。今天我们聊聊CAN协议的基础。说实话,很多刚入行的朋友一上来就盯着波特率、终端电阻这些参数调,结果出了问题根本不知道从哪查起。我个人习惯是,先把协议本身吃透,再去碰硬件。这一章,我们就从CAN协议的分层结构和五种报文帧格式说起。
2.1 CAN协议的分层结构
CAN协议本身其实不复杂,但它分了两层:物理层和数据链路层。你想想看,这就像寄快递——物理层是快递车和公路,数据链路层就是包裹上的面单和打包规则。
- 物理层:负责信号的传输,比如差分电压、位时序、同步。说白了,就是0和1怎么在CAN_H和CAN_L两根线上跑起来。
- 数据链路层:负责组帧、仲裁、错误检测、应答。这一层决定了谁能发、发什么、发错了怎么办。
我在项目中遇到过一位同事,他调CAN通信死活不通,最后发现是物理层的位采样点设置不对。嗯,这里要注意:物理层出问题,数据链路层再牛也白搭。
2.2 CAN报文帧格式概览
CAN总线上跑的数据,我们叫它“报文”。一共有五种帧类型:
| 帧类型 | 用途 | 谁发 |
|---|---|---|
| 数据帧 | 发送数据 | 发送节点 |
| 远程帧 | 请求数据 | 接收节点 |
| 错误帧 | 报告总线错误 | 检测到错误的节点 |
| 过载帧 | 请求延迟发送 | 接收节点(忙时) |
| 帧间隔 | 帧与帧之间的分隔 | 总线空闲 |
我个人建议,先把数据帧和远程帧搞明白,这两个是日常开发中最常见的。错误帧和过载帧属于“异常处理”,帧间隔则是总线的“呼吸节奏”。
2.3 数据帧(Data Frame)
数据帧是CAN总线上最常用的帧。它负责把数据从一个节点传到另一个节点。数据帧又分两种格式:标准帧(11位ID)和扩展帧(29位ID)。
一个完整的数据帧包含以下几个段:
- 帧起始(SOF):1个显性位,告诉总线“我要开始发了”。
- 仲裁段:包含ID和RTR位。标准帧11位ID,扩展帧29位ID。RTR位用来区分数据帧(显性)和远程帧(隐性)。
- 控制段:包含IDE位、保留位和DLC(数据长度码)。DLC告诉你后面跟了多少字节数据,范围0~8。
- 数据段:0~8字节的数据。这是真正要传的内容。
- CRC段:15位CRC校验码+1位CRC界定符。用来检查数据有没有传错。
- ACK段:1位ACK槽+1位ACK界定符。接收节点如果正确收到,会在ACK槽发显性位应答。
- 帧结束(EOF):7个隐性位,表示帧结束。
重点记忆:数据帧的仲裁段决定了总线的优先级。ID越小,优先级越高。我在调试多节点通信时,经常用这个特性来保证关键报文不被抢断。
2.4 远程帧(Remote Frame)
远程帧说白了就是“请求帧”。一个节点想从另一个节点拿数据,就发一个远程帧。远程帧和数据帧的结构几乎一样,唯一的区别是:远程帧没有数据段,而且RTR位是隐性(1)。
举个例子:ECU_A想知道ECU_B的当前车速,ECU_A就发一个远程帧,ID填车速对应的ID。ECU_B收到后,就会发一个数据帧回来。
避坑指南:我曾经在项目中遇到一个bug,远程帧的DLC设置错了,导致接收节点不知道要回多少字节的数据。记住:远程帧的DLC必须和期望返回的数据帧的DLC一致,否则对方可能不回数据。
2.5 错误帧(Error Frame)
错误帧是CAN总线自我保护的机制。任何一个节点检测到错误,就会立刻发送错误帧,通知其他节点“刚才那帧有问题,别用了”。
错误帧由两部分组成:
- 错误标志:6个连续相同位(显性或隐性,取决于错误类型)。
- 错误界定符:8个隐性位。
错误帧有主动和被动两种模式。主动错误节点发6个显性位,被动错误节点发6个隐性位。嗯,这里要注意:如果一个节点频繁发错误帧,它可能会从主动错误状态变成被动错误状态,甚至进入总线关闭状态。
警告:我曾经调试过一个项目,总线莫名其妙频繁报错。最后发现是一个节点的CAN收发器供电不稳,导致它不断发错误帧,把整个总线都拖垮了。所以,遇到总线错误,先查硬件供电和终端电阻。
2.6 过载帧(Overload Frame)
过载帧的作用是“请求等一下”。当一个节点太忙,处理不过来时,它可以发过载帧,让发送节点等一等再发。
过载帧的结构和错误帧很像:
- 过载标志:6个显性位。
- 过载界定符:8个隐性位。
过载帧在实际项目中用得不多。我做了这么多年,也就碰到过一两次。一般出现在节点CPU负载过高,或者中断响应不及时的情况下。
2.7 帧间隔(Interframe Space)
帧间隔不是真正的“帧”,它是帧与帧之间的空闲时间。说白了,就是总线喘口气的时间。
帧间隔包含:
- 间歇场:3个隐性位。
- 总线空闲:任意长度的隐性位,直到有节点开始发送。
对于被动错误节点,帧间隔还会多一个“挂起传输”段(8个隐性位)。这是为了让被动错误节点在发完一帧后多等一会儿,避免它抢总线。
总结一下:五种帧格式,数据帧和远程帧是“干活”的,错误帧和过载帧是“处理异常”的,帧间隔是“休息”的。你只要把数据帧的结构记熟,其他帧基本都能触类旁通。
好了,这一章的内容就到这里。下一章我们聊聊CAN的位时序和同步,这可是调通物理层的关键。有什么问题,欢迎在群里交流。