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数据帧包含以下部分:

  1. SOF(帧起始):1个显性位,告诉所有节点"我要发数据了"
  2. 仲裁场:11位ID + RTR位,决定谁能抢到总线
  3. 控制场:IDE位 + 保留位 + DLC(数据长度码)
  4. 数据场:0~8字节,你要传的真正数据
  5. CRC场:15位CRC校验 + 1位CRC界定符
  6. ACK场:接收节点在这里回应"我收到了"
  7. 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Ω终端电阻,而且总线两端都要加。

选型时要注意几点:

  1. 速率匹配:收发器支持的速率要覆盖你的需求。比如TJA1050支持最高1Mbps。
  2. 电平兼容:3.3V的STM32和5V的收发器之间需要电平转换,或者选3.3V的收发器如SN65HVD230。
  3. 保护功能:车载环境建议选带过压保护、热关断的收发器。

最后分享一个调试技巧:用示波器看CAN_H和CAN_L的波形。正常通信时,两根线应该是镜像对称的,幅值约2V。如果波形不对称,八成是终端电阻没焊好或者收发器供电有问题。

好了,CAN总线的基础就聊到这儿。下一节咱们会深入CAN的仲裁机制和位时序配置,那才是真正考验功底的地方。