2. CAN总线基础:从物理层到报文格式
大家好,我是你们的嵌入式讲师。今天咱们聊聊CAN总线的基础知识。说实话,CAN总线是我在项目中打交道最多的现场总线之一,从早期的车身控制到现在的UDS诊断,它几乎无处不在。你想想看,一条双绞线就能让几十个节点可靠通信,这事儿本身就挺神奇的。
2.1 CAN总线物理层:差分信号与电平
CAN总线的物理层,说白了就是怎么在线上传数据。它用的是差分信号,也就是两根线——CAN_H和CAN_L。我刚开始接触时总觉得这玩意儿玄乎,后来拆了几个ECU才明白,其实原理很简单。
总线有两种状态:
- 显性电平(Dominant):CAN_H比CAN_L高约2V,逻辑上代表"0"
- 隐性电平(Recessive):CAN_H和CAN_L电压接近,约2.5V,逻辑上代表"1"
这里有个关键点:显性电平会"覆盖"隐性电平。什么意思呢?就是只要有一个节点拉低总线,总线就变成显性。这个特性在后面讲仲裁时会用到。
实际经验:我在做车载诊断仪时,遇到过总线电平异常的问题。用示波器一量,发现CAN_H对地短路了。嗯,这种问题在实车线束中挺常见的,所以设计时一定要加保护电路。
2.2 CAN总线数据链路层:帧结构与位填充
数据链路层负责把物理层的比特流组织成有意义的帧。CAN的帧结构设计得非常精巧,我每次讲到这里都觉得当年的工程师们真是天才。
标准CAN数据帧包含以下部分:
- SOF(帧起始):1个显性位,告诉所有节点"我要发数据了"
- 仲裁场:11位ID + RTR位,决定谁能抢到总线
- 控制场:IDE位 + 保留位 + DLC(数据长度码)
- 数据场:0~8字节,你要传的真正数据
- CRC场:15位CRC校验 + 1位CRC界定符
- ACK场:接收节点在这里回应"我收到了"
- EOF(帧结束):7个隐性位
你可能会问:为什么数据最多8个字节?其实这是早期设计时的权衡。8字节对于实时控制足够了,而且能保证实时性。后来有了CAN FD,数据场可以到64字节,那是后话了。
避坑指南:我曾经在写CAN驱动时,忽略了位填充规则。CAN协议规定,连续5个相同电平后必须插入一个相反电平。如果不处理这个,接收端可能会失去同步。嗯,那次调试花了我整整一个下午。
2.3 CAN报文格式:标准帧与扩展帧
CAN报文有两种格式,我习惯叫它们"短ID"和"长ID":
| 特性 | 标准帧(CAN 2.0A) | 扩展帧(CAN 2.0B) |
|---|---|---|
| ID长度 | 11位 | 29位 |
| 最大节点数 | 约2048个 | 约5.3亿个 |
| IDE位 | 显性(0) | 隐性(1) |
| 应用场景 | 传统车身控制 | 诊断、多节点系统 |
我个人建议,做UDS诊断时优先用扩展帧。为什么呢?因为29位ID可以编码更多信息,比如源地址、目标地址、服务类型等。我在一个项目中就吃过亏,用标准帧做诊断,结果ID不够用,后来全改了。
这里再提一下远程帧(RTR帧)。它没有数据场,用来请求其他节点发送数据。说实话,我在实际项目中很少用远程帧,因为大多数场景下用数据帧轮询更可靠。
2.4 CAN控制器与收发器:硬件选型与配合
搞CAN开发,你得清楚两个芯片的分工:
- CAN控制器:处理协议层,比如帧封装、位填充、CRC计算。STM32内置的bxCAN就是控制器。
- CAN收发器:处理物理层,把控制器的数字信号转成差分信号。常见的有TJA1050、SN65HVD230。
我习惯这么理解:控制器是"大脑",收发器是"嘴巴"。大脑想好说什么,嘴巴负责喊出去。
重要提醒:STM32的CAN控制器和收发器之间需要匹配电阻。我见过有人直接把控制器引脚连到收发器上,结果通信不稳定。正确的做法是:在CAN_H和CAN_L之间加120Ω终端电阻,而且总线两端都要加。
选型时要注意几点:
- 速率匹配:收发器支持的速率要覆盖你的需求。比如TJA1050支持最高1Mbps。
- 电平兼容:3.3V的STM32和5V的收发器之间需要电平转换,或者选3.3V的收发器如SN65HVD230。
- 保护功能:车载环境建议选带过压保护、热关断的收发器。
最后分享一个调试技巧:用示波器看CAN_H和CAN_L的波形。正常通信时,两根线应该是镜像对称的,幅值约2V。如果波形不对称,八成是终端电阻没焊好或者收发器供电有问题。
好了,CAN总线的基础就聊到这儿。下一节咱们会深入CAN的仲裁机制和位时序配置,那才是真正考验功底的地方。