第2章 CAN总线入门:物理层特性、报文帧结构与仲裁机制
大家好,我是你们的老朋友。今天咱们聊聊CAN总线。
说实话,搞OBD开发,CAN总线是绕不开的坎。我当年刚入行时,对着示波器看CAN信号,愣是看了三天才搞明白高低电平的关系。嗯,今天我就把这些经验掰开揉碎了讲给你听。
2.1 CAN总线物理层特性
CAN总线物理层,说白了就是信号怎么在线上跑的问题。
它用的是差分信号传输。什么意思?就是两根线——CAN_H和CAN_L,靠电压差来传递信息。
关键点:CAN总线有两种状态——显性(Dominant)和隐性(Recessive)。
- 显性电平:CAN_H ≈ 3.5V,CAN_L ≈ 1.5V,压差约2V,代表逻辑"0"
- 隐性电平:CAN_H ≈ 2.5V,CAN_L ≈ 2.5V,压差约0V,代表逻辑"1"
我在项目中遇到过一个问题:某款车在低温环境下CAN通信偶尔中断。查了半天,发现是终端电阻阻值漂移了。记住,CAN总线两端必须各接一个120Ω的终端电阻,这是用来消除信号反射的。
我的习惯:设计CAN节点时,我会在PCB上预留终端电阻的位置。调试时先用万用表量一下总线电阻——正常应该在60Ω左右(两个120Ω并联)。如果不对,先别急着查代码。
CAN总线的传输速率常见的有:125kbps、250kbps、500kbps。OBD-II标准要求至少支持250kbps。速率越高,总线长度就得越短。500kbps时,总线长度最好不要超过100米。
2.2 CAN报文帧结构
CAN总线上一共就四种帧:数据帧、远程帧、错误帧、过载帧。咱们重点讲前三种。
2.2.1 数据帧
数据帧是干活的主力。它负责把数据从一个节点送到另一个节点。
一个标准数据帧(11位ID)长这样:
帧起始(1bit) + 仲裁场(12bit) + 控制场(6bit) + 数据场(0~8字节) + CRC场(16bit) + 应答场(2bit) + 帧结束(7bit)
你想想看,一个数据帧最多带8个字节的数据。为什么是8个?不是16个?我猜当年设计者觉得8个字节够用了,毕竟汽车上的传感器数据大多不超过4个字节。不过现在有些高端应用确实觉得8字节不够用,所以有了CAN FD(灵活数据速率),能到64字节。
注意:OBD-II标准中,请求和响应报文都使用数据帧。远程帧在OBD中很少用,但你要知道它的存在。
2.2.2 远程帧
远程帧,说白了就是"请求帧"。一个节点发远程帧,意思是"谁有数据?给我发一份"。
远程帧和数据帧长得几乎一样,区别在于:
- 远程帧的RTR位(远程发送请求位)为隐性(1)
- 数据帧的RTR位为显性(0)
- 远程帧没有数据场
我记得有一次调试,发现某个传感器节点不响应请求。查了半天,原来是对方把远程帧当数据帧处理了。嗯,这种低级错误我也犯过。
2.2.3 错误帧
错误帧是CAN总线的"警察"。一旦检测到错误,任何节点都可以发送错误帧,把当前报文废掉。
错误帧由两部分组成:
- 错误标志:6个连续的显性位(主动错误)或6个连续的隐性位(被动错误)
- 错误界定符:8个连续的隐性位
为什么会这样设计?你想想看,6个连续的显性位在正常报文里是不可能出现的(CAN用了位填充,最多5个连续相同位)。所以一旦出现6个显性位,所有节点都知道——出错了。
避坑指南:我曾经遇到一个项目,CAN总线频繁出现错误帧。用示波器一看,发现是某个节点的时钟精度不够,导致位采样点偏移。后来我把所有节点的晶振都换成了0.5%精度的,问题解决。所以,别在晶振上省钱。
2.3 CAN总线仲裁机制
仲裁机制是CAN总线最巧妙的设计之一。它解决了"多个节点同时发送时谁先发"的问题。
原理很简单:ID越小,优先级越高。
具体怎么工作的?
- 所有节点同时发送仲裁场(ID + RTR位)
- 每个节点在发送每一位时,同时监听总线电平
- 如果自己发送的是隐性位(1),但总线上是显性位(0),说明有更高优先级的节点在发,自己立即退出
- 退出节点转为接收模式,等总线空闲后再重试
说白了,这就是"线与"逻辑。显性位(0)能覆盖隐性位(1)。谁发的ID小(0多),谁就能赢。
举个例子:
节点A发ID=0x7DF(二进制:111 1101 1111)
节点B发ID=0x7E0(二进制:111 1110 0000)
从第7位开始,A发0,B发1。总线被A拉成0,B检测到总线与自己发送的不一致,B退出。
所以,0x7DF的优先级高于0x7E0。
我在项目中遇到过一个问题:某款OBD适配器在总线上发送请求时,总是被其他节点"抢线"。后来发现是ID设得太大了(0x7E8),而车上其他ECU的ID都在0x7DF以下。改成0x7DF后,问题解决。
重要提醒:OBD-II标准中,诊断请求的ID通常是0x7DF(11位)或0x18DB33F1(29位)。这个ID的优先级在整车网络中属于中等偏上。如果你自己开发设备,别乱改ID,否则可能被其他ECU"欺负"。
2.4 小结
今天的内容就这些。总结一下:
- CAN总线用差分信号,显性=0,隐性=1
- 数据帧是主力,远程帧是请求,错误帧是警察
- 仲裁靠ID大小,ID越小越优先
下一章咱们聊CAN控制器和收发器的选型,以及怎么用STM32的CAN外设。到时候我会拿出我珍藏的代码库,手把手教你配置。
记住,搞CAN总线,示波器是你的好朋友。别光看书,动手测一测,比什么都强。
公众号:蓝海资料掘金营,微信deep3321