2. CAN协议基础:CAN总线物理层特性、差分信号原理、CAN帧结构

大家好,我是你们的老朋友。今天咱们来聊聊CAN总线的基础知识。说实话,CAN协议在汽车电子里太常见了,几乎每个ECU都离不开它。我当年刚入行时,第一次调试CAN通信就遇到了信号干扰问题,折腾了两天才搞定。所以今天我把这些经验都揉碎了讲给你听。

2.1 CAN总线物理层特性

CAN总线物理层,说白了就是信号怎么在线上跑的问题。它用的是两根线——CAN_H和CAN_L。这两根线绞在一起,形成双绞线结构。为什么要绞?为了抗干扰。你想想看,两根线绞在一起,外部电磁干扰对两根线的影响几乎一样,这就为后面的差分信号打下了基础。

CAN总线的电平状态有两种:显性(Dominant)和隐性(Recessive)。显性电平对应逻辑0,隐性电平对应逻辑1。这里有个关键点:显性电平会覆盖隐性电平。也就是说,只要有一个节点发送显性电平,总线就呈现显性状态。这个特性在总线仲裁时特别有用。

我习惯把CAN总线的物理层特性总结成一张表,方便你对照:

参数 高速CAN(ISO 11898-2) 低速CAN(ISO 11898-3)
最大速率 1 Mbps 125 kbps
总线长度(1 Mbps时) 约40米 约500米
显性电平电压差 约2V 约1.5V
隐性电平电压差 约0V 约0V
终端电阻 120Ω(两端各一个) 不强制要求
我的经验: 实际项目中,终端电阻一定要加对位置。我曾经遇到过一个案例,终端电阻加在了中间节点上,结果总线信号反射严重,通信时好时坏。记住,终端电阻必须放在总线的最两端。

2.2 差分信号原理

差分信号是CAN总线的核心。为什么不用单端信号?因为汽车环境太嘈杂了。发动机点火、电机运转、各种电磁干扰,单端信号在这种环境下根本扛不住。

差分信号的工作原理其实很简单:发送端在CAN_H和CAN_L上分别输出互补的信号。接收端只关心两根线之间的电压差,不关心它们对地的绝对电压。这样一来,外部干扰同时作用在两根线上,电压差基本不变,信号就保住了。

具体来说:

  • 显性状态: CAN_H电压约3.5V,CAN_L电压约1.5V,差分电压约2V
  • 隐性状态: CAN_H和CAN_L电压都约2.5V,差分电压约0V

嗯,这里要注意一点:差分电压的阈值是有容差的。不同厂家的CAN收发器,阈值可能略有不同。我建议你在选型时留出20%的余量,别卡着极限值设计。

避坑指南: 我曾经在项目里遇到过CAN总线共模电压漂移的问题。原因是接地不良,导致CAN_H和CAN_L的对地电压整体偏移了2V多。虽然差分电压没变,但收发器的共模输入范围只有-2V到+7V,差点超出范围。所以,CAN总线的地线一定要接好

2.3 CAN帧结构

CAN协议定义了四种帧类型:数据帧、远程帧、错误帧和过载帧。咱们重点讲前三种,过载帧用得少,先放一放。

2.3.1 数据帧

数据帧是干活的主力。它负责把数据从一个节点传到另一个节点。标准格式的数据帧长这样:

SOF + 11位ID + RTR + IDE + r0 + 4位DLC + 0~8字节数据 + 15位CRC + CRC分隔符 + ACK + ACK分隔符 + EOF

我拆开来讲:

  • SOF(帧起始): 1位显性电平,告诉所有节点"我要发数据了"
  • ID(标识符): 标准帧11位,扩展帧29位。ID越小,优先级越高
  • RTR(远程发送请求): 数据帧里是显性(0),远程帧里是隐性(1)
  • DLC(数据长度码): 4位,表示数据字节数,范围0~8
  • 数据段: 0~8字节,想传啥传啥
  • CRC: 15位校验码,加上1位分隔符
  • ACK: 接收节点在ACK槽里发送显性电平,表示"我收到了"
  • EOF: 7位隐性电平,表示帧结束
我的习惯: 设计CAN报文时,尽量把频繁发送的报文ID设小一点。比如发动机转速报文用0x100,车窗控制用0x500。这样高优先级的报文能更快抢到总线。

2.3.2 远程帧

远程帧,说白了就是"请求帧"。一个节点发远程帧,意思是"谁有数据?给我发一份"。远程帧的结构和数据帧几乎一样,唯一的区别是RTR位为隐性(1),而且没有数据段。

举个例子:ECU_A想获取ECU_B的传感器数据,ECU_A就发一个远程帧,ID填ECU_B的数据帧ID。ECU_B收到后,就会发送对应的数据帧。

注意: 远程帧在实际项目中用得不多。我建议你尽量用数据帧主动上报的方式,而不是用远程帧去轮询。因为远程帧会增加总线负载,而且响应时间不可控。除非是诊断场景,否则少用远程帧。

2.3.3 错误帧

错误帧是CAN总线的"交警"。当节点检测到总线错误时,就会发送错误帧,通知所有节点"刚才那帧有问题,别用了"。

错误帧由两部分组成:

  • 错误标志: 6位相同电平(显性或隐性),主动错误节点发6位显性,被动错误节点发6位隐性
  • 错误分隔符: 8位隐性电平

CAN协议定义了五种错误类型:

  1. 位错误: 发送节点监控总线,发现发送的电平和总线电平不一致
  2. 填充错误: 连续5个相同电平后,没有插入相反电平
  3. CRC错误: 接收节点计算的CRC和发送的不一致
  4. 格式错误: 帧格式不符合规范
  5. ACK错误: 发送节点在ACK槽没收到显性电平

为什么会这样设计?因为CAN总线要求高可靠性。任何一个节点发现错误,都要立即通知大家,避免错误数据被误用。

避坑指南: 我曾经调试过一个项目,CAN总线频繁出现错误帧。查了半天,发现是某个节点的晶振精度不够,导致位时序偏差太大。换了个高精度晶振,问题就解决了。所以,CAN节点的时钟精度一定要达标,尤其是高速CAN。

好了,CAN协议的基础就讲到这里。下一章咱们聊聊CAN的位时序和同步机制,这可是理解CAN通信质量的关键。有什么问题,欢迎随时交流。