4、CAN总线基础回顾:CAN帧结构、CAN标识符与优先级、CAN总线仲裁机制
各位同学,咱们今天聊点实在的。UDS诊断跑在CAN总线上,你要是对CAN帧都不熟,那后面调试起来会非常痛苦。我当年刚入行时,就吃过这个亏——拿着示波器看半天波形,愣是不知道哪段是数据、哪段是ID。所以这一节,咱们把CAN总线的基础彻底捋一遍。
4.1 CAN帧结构:数据是怎么装进“信封”的?
CAN总线上的数据,说白了就是一个个“帧”。就像你寄快递,得有个信封,写上地址、贴好邮票。CAN帧也一样,有固定的格式。
咱们最常用的是数据帧,它负责把数据从A点送到B点。一个标准的数据帧长什么样?我习惯把它拆成几个关键部分:
- 帧起始(SOF):一个显性位,告诉总线上所有节点:“我要开始说话了!”
- 仲裁场:这里包含标识符(ID)和RTR位。ID决定了谁有更高的发言权。
- 控制场:包含IDE位和DLC(数据长度码)。DLC告诉你后面跟了多少字节的数据,范围是0到8。
- 数据场:0~8个字节,这就是你要传的“干货”。UDS诊断的请求和响应,就装在这里。
- CRC场:循环冗余校验。说白了就是检查数据有没有被干扰。
- ACK场:应答位。接收节点如果正确收到了,就会在这里拉一个显性位,告诉发送方:“我收到了!”
- 帧结束(EOF):7个隐性位,表示这帧说完了。
重点记忆:数据场最多8个字节。UDS诊断报文如果超过8字节,就得用“长帧”或者“多帧传输”了。这个咱们后面会细讲。
嗯,这里要注意:CAN帧还有远程帧、错误帧和过载帧。远程帧是用来请求数据的,它没有数据场。错误帧是节点发现总线出错时自动发的。过载帧则是告诉对方“我忙,慢点发”。不过咱们做UDS诊断,打交道最多的还是数据帧。
4.2 CAN标识符与优先级:谁嗓门大谁先走
CAN总线有个很有意思的特点:没有主从节点。所有节点都能同时发数据。那问题来了——如果两个节点同时发,总线听谁的?
答案就在标识符(ID)上。CAN的ID不是地址,而是优先级。ID越小,优先级越高。你想想看,总线上同时出现显性位(0)和隐性位(1)时,显性位会“覆盖”隐性位。所以ID数值小的帧,它的显性位更多,自然就赢了。
我举个例子:
| 节点 | ID(二进制) | 优先级 |
|---|---|---|
| ECU_A | 0x100 (001 0000 0000) | 高 |
| ECU_B | 0x200 (010 0000 0000) | 低 |
如果ECU_A和ECU_B同时发,总线仲裁时,ECU_A的ID第一位是0(显性),ECU_B的第一位是1(隐性)。显性胜出,ECU_A继续发,ECU_B乖乖退出发送,等下次机会。
个人经验:我在项目中遇到过一个问题——诊断仪发请求时,总被其他高优先级的报文打断,导致诊断超时。后来我把诊断请求的ID设得比所有应用报文都小,问题就解决了。记住:诊断报文优先级一定要高,否则关键时刻抢不到总线。
CAN有标准帧和扩展帧两种格式。标准帧ID是11位,扩展帧ID是29位。扩展帧的IDE位为1,表示后面还有18位ID。说白了,扩展帧就是给ID不够用时用的。咱们做UDS诊断,标准帧用得更多,因为11位ID在大多数场景下够用了。
4.3 CAN总线仲裁机制:一场“文明”的抢话
仲裁机制,说白了就是解决冲突的规则。CAN总线的仲裁是非破坏性的——赢的节点继续发,输的节点自动退出发送,不会破坏正在传输的数据。
具体怎么仲裁?我一步步说:
- 所有要发送的节点,同时把ID的每一位往总线上放。
- 每个节点在发送的同时,也在监听总线电平。
- 如果自己发的是隐性位(1),但总线上是显性位(0),说明有更高优先级的节点在发。自己立刻停止发送,转为接收模式。
- 仲裁胜出的节点,继续发送剩余的数据。
这个过程发生在仲裁场。仲裁结束后,只有一个节点能继续发送。其他节点会在总线空闲时重新尝试发送。
避坑指南:我曾经遇到过一个问题——两个ECU的ID设成了一样的。结果它们同时发数据时,仲裁无法分出胜负,最终导致总线错误。所以,同一个CAN网络上,每个节点的ID必须唯一。这是基本规则,千万别犯低级错误。
你可能会问:如果两个节点ID相同,但一个发数据帧,一个发远程帧,怎么办?这时候看RTR位。数据帧的RTR是显性位,远程帧的RTR是隐性位。所以数据帧优先级更高。嗯,这个细节在UDS诊断中不常用,但面试时经常被问到。
4.4 实战中的CAN帧分析
咱们做UDS诊断,经常要抓CAN报文来分析。我习惯用CANalyzer或者PCAN-View。抓到的报文长这样:
时间戳 ID DLC 数据
0.001234 0x7DF 8 02 10 03 00 00 00 00 00
0.001567 0x7E8 8 06 50 03 00 32 01 F4 00
第一行是诊断请求:ID=0x7DF(功能寻址),DLC=8,数据是“02 10 03”。02表示后面有2个字节,10是诊断会话控制服务ID,03是子功能(扩展诊断会话)。
第二行是诊断响应:ID=0x7E8(物理响应),DLC=8,数据是“06 50 03 00 32 01 F4”。06表示后面有6个字节,50是响应服务ID(10+0x40),03表示成功,后面是具体参数。
你看,理解了CAN帧结构,再看这些报文就一目了然了。ID决定谁发、谁收;DLC决定数据长度;数据场里装的才是UDS的“灵魂”。
总结一下:CAN帧结构是UDS诊断的“运输工具”。标识符决定了优先级,仲裁机制保证了总线不乱。做UDS开发,这三样东西必须烂熟于心。下一节咱们会讲UDS的寻址方式——物理寻址和功能寻址的区别,以及怎么在CAN帧里实现。