4、CAN报文分析:标准帧与扩展帧区别、数据帧、远程帧、错误帧、过载帧、帧间隔、位填充机制
各位同学,咱们今天聊点硬核的——CAN报文。
说实话,搞UDS诊断,你天天都在跟CAN报文打交道。报文看不懂,诊断就无从谈起。我刚开始做车载项目那会儿,拿着逻辑分析仪抓了一堆波形,愣是分不清哪个是标准帧哪个是扩展帧。后来被老工程师点了一下,才恍然大悟。
今天我就把CAN报文的这些门道,掰开了揉碎了讲给你听。
4.1 标准帧 vs 扩展帧:到底差在哪?
CAN总线最早用的是标准帧,11位ID。后来发现11位不够用了,就搞了个扩展帧,29位ID。
你想想看,一辆车上几十个ECU,每个ECU又有几十个诊断服务,11位ID哪够分?
标准帧和扩展帧的区别,说白了就两点:
- ID长度不同:标准帧11位,扩展帧29位
- 帧格式不同:扩展帧多了IDE位和扩展ID段
我个人的习惯是:诊断通信尽量用扩展帧。为什么呢?因为UDS诊断的ID分配往往需要更多的地址空间。你想想,一个诊断请求、一个诊断响应,再加上功能寻址、物理寻址,11位ID真的捉襟见肘。
关键区别表:
| 特性 | 标准帧 | 扩展帧 |
|---|---|---|
| ID位数 | 11位 | 29位 |
| IDE位 | 0(显性) | 1(隐性) |
| 最大ID值 | 0x7FF | 0x1FFFFFFF |
| 数据场长度 | 0-8字节 | 0-8字节 |
嗯,这里要注意:IDE位是区分标准帧和扩展帧的关键。你在解析报文时,先看IDE位,就能知道后面该怎么读。
4.2 数据帧:最常用的报文类型
数据帧,就是用来传数据的。UDS诊断的请求和响应,全是通过数据帧来传递的。
数据帧的结构是这样的:
帧起始(SOF) + 仲裁场(11/29位ID + RTR + IDE) + 控制场(4位DLC) + 数据场(0-8字节) + CRC场 + ACK场 + 帧结束(EOF)
我在项目中遇到过一个问题:有个同事写代码,DLC(数据长度码)总是设成8,哪怕只传2个字节的数据。结果呢?总线负载率飙升,诊断响应也变慢了。
所以我的建议是:DLC一定要跟实际数据长度匹配。传多少字节,DLC就设多少。别浪费总线带宽。
4.3 远程帧:问而不答?
远程帧,说白了就是「请求数据」的帧。它没有数据场,只有ID和RTR位。
RTR位是啥?就是远程发送请求位。数据帧的RTR=0,远程帧的RTR=1。
远程帧的应用场景不多,但在某些诊断协议里,会用远程帧来查询ECU的状态。我个人不太推荐在UDS诊断里用远程帧,因为UDS本身就有完善的请求-响应机制,没必要再用远程帧来添乱。
小技巧: 如果你在总线上看到RTR=1的帧,别慌。它只是在问「你有没有数据要发给我?」而已。
4.4 错误帧:总线上的「警报」
错误帧,是CAN节点发现自己出错时主动发出的。它由错误标志和错误界定符组成。
错误帧有两种:
- 主动错误帧:6个显性位 + 8个隐性位
- 被动错误帧:6个隐性位 + 8个隐性位
我曾经调试过一个项目,总线老是莫名其妙地出现错误帧。查了半天,发现是一个ECU的CAN收发器坏了,一直在发错误标志。嗯,那次之后我就养成了习惯:先检查硬件,再怀疑软件。
避坑指南: 错误帧出现频繁时,别急着改代码。先看看总线终端电阻对不对,CANH/CANL有没有短路,节点供电稳不稳。我曾经因为一个虚焊的终端电阻,折腾了整整两天。
4.5 过载帧:总线太忙了
过载帧,是节点告诉总线「我忙不过来了,慢点发」。它跟错误帧有点像,但含义完全不同。
过载帧由过载标志(6个显性位)和过载界定符(8个隐性位)组成。
说实话,过载帧在现在的CAN总线里已经很少见了。因为现在的CAN控制器处理速度都很快,很少会出现处理不过来的情况。但如果你在总线上看到过载帧,那就要注意了——可能是某个节点的CPU负载太高了。
4.6 帧间隔:总线的「呼吸」
帧间隔,就是两帧之间的空闲时间。它由3个隐性位组成。
为什么要有帧间隔?
说白了,就是给总线一点喘息的时间。让每个节点都能检测到总线空闲,然后公平地竞争总线使用权。
我刚开始做CAN开发时,总觉得帧间隔是浪费带宽。后来才明白,没有帧间隔,总线仲裁就会乱套。你想想看,如果两帧之间没有间隔,节点怎么知道上一帧结束了?
4.7 位填充机制:保证同步的「小聪明」
位填充,是CAN总线的一个巧妙设计。
规则很简单:连续发送5个相同位后,自动插入一个相反位。
比如你连续发了5个1,那第6位就自动变成0。接收端看到这个0,就知道这是填充位,不是数据。
为什么要这么做?
因为CAN节点是靠电平跳变来同步时钟的。如果连续太多相同的位,没有跳变,节点就会失去同步。位填充保证了总线上最多5个位就会出现一次跳变。
举个例子:
你要发送的数据:11111 00000 111
位填充后的数据:111110 000001 111
注意看,填充位我用粗体标出来了。接收端收到后,会自动去掉这些填充位,还原原始数据。
嗯,这里有个坑:位填充只发生在SOF到CRC场之间。ACK场和EOF是不做位填充的。我见过有人写代码时把ACK场也做了位填充,结果总线直接报错。
小结
今天咱们把CAN报文的几种类型都过了一遍。标准帧和扩展帧的区别要记牢,数据帧是诊断的主力,远程帧少用,错误帧和过载帧要能识别,帧间隔别忽略,位填充机制要理解。
下一章,咱们会讲CAN的位时序和同步机制。到时候你会发现,今天讲的这些内容,都是理解位时序的基础。
好了,今天就到这儿。有问题随时问我。