1. CAN总线基础:从起源到物理层,一个老工程师的实战笔记

各位同学好,我是老李。今天咱们聊聊CAN总线的基础。说实话,我接触CAN总线快二十年了,从最早的博世CAN 2.0A一直做到现在的CAN FD。每次带新人,我都是从这些最基础的东西讲起。别小看这些基础,我见过太多工程师因为忽略物理层特性,在实车上吃尽苦头。

1.1 CAN协议的起源:为什么会有CAN?

上世纪80年代,汽车电子开始爆发。那时候一辆车里有几十个ECU,每个ECU之间用点对点的线束连接。你想想看,一个豪华车可能有上百公斤的线束,又重又贵,还容易出故障。

1983年,博世的工程师们坐不住了。他们想要一种新的总线,能解决几个核心痛点:

  • 减少线束:所有节点共享一对双绞线
  • 高可靠性:在电磁干扰严重的汽车环境里稳定工作
  • 实时性:关键消息(比如刹车信号)必须优先传输
  • 错误检测:能自动发现并重发错误帧

1986年,博世正式发布了CAN协议。我记得第一次看到CAN协议文档时,觉得这玩意儿设计得太巧妙了——用两根线就搞定了所有通信,而且天生带优先级仲裁。后来奔驰、宝马、大众纷纷采用,CAN就成了汽车界的标准配置。

核心要点:CAN不是凭空造出来的,它是为了解决汽车电子系统日益复杂的线束问题和可靠性需求而生的。说白了,就是被逼出来的。

1.2 物理层特性:CAN_H和CAN_L的秘密

CAN总线物理层用的是差分信号,两根线分别叫CAN_H(高电平线)和CAN_L(低电平线)。嗯,这里要注意,千万别把这两根线接反了,我刚开始做项目时就犯过这个低级错误。

CAN总线的电平状态分为两种:

状态 CAN_H电压 CAN_L电压 差分电压
显性(Dominant) 3.5V 1.5V 2.0V
隐性(Recessive) 2.5V 2.5V 0V

为什么用差分信号?说白了就是为了抗干扰。汽车发动机舱里电磁环境有多恶劣,做过实车测试的都知道。差分信号的好处是:外部干扰对两根线的影响是相同的,接收器只关心两根线的电压差,所以共模干扰就被抵消了。

我的经验:在Zephyr RTOS里配置CAN控制器时,一定要确认物理层的匹配。比如你用的是3.3V的CAN收发器,那CAN_H和CAN_L的电压范围会略有不同。我曾经在一个项目里混用了5V和3.3V的收发器,结果通信时好时坏,查了两天才发现是电平不匹配。

1.3 差分信号原理:为什么两根线比一根线强?

咱们来深入聊聊差分信号。你可能会问:为什么不用单端信号?单端信号一根线就够了啊。

我举个例子你就明白了。假设你有一根信号线,从ECU_A传到ECU_B。如果这时候旁边有个大功率电机启动,产生的电磁干扰会在信号线上感应出噪声。单端信号里,这个噪声和原始信号混在一起,接收端根本分不清哪个是信号哪个是噪声。

差分信号就不一样了。CAN_H和CAN_L绞在一起,外部干扰对两根线的影响几乎一样。接收器只计算CAN_H - CAN_L的差值,干扰就被抵消了。这就是所谓的共模抑制

我记得有一次在实验室做EMC测试,用单端信号的总线在100V/m的场强下就挂了,而CAN总线撑到了200V/m还能正常工作。这就是差分信号的硬实力。

避坑指南:我曾经在一个项目中,为了省成本,用了非屏蔽的双绞线。结果在实车测试时,只要发动机转速超过4000rpm,CAN总线就开始丢帧。后来换成屏蔽双绞线,问题立刻解决。记住:CAN总线一定要用双绞线,而且绞距要符合规范(通常每米30-40绞)。

1.4 总线拓扑结构:CAN总线的物理连接方式

CAN总线采用多主总线拓扑结构。什么意思?就是总线上所有节点都是平等的,没有主从之分。任何一个节点都可以随时发送数据,谁先抢到总线谁就发。

典型的CAN总线拓扑长这样:

┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
│ 节点1   │    │ 节点2   │    │ 节点3   │    │ 节点4   │
│ (ECU)   │    │ (ECU)   │    │ (ECU)   │    │ (ECU)   │
└────┬────┘    └────┬────┘    └────┬────┘    └────┬────┘
     │              │              │              │
     └──────────────┴──────────────┴──────────────┘
                    │
              ┌─────┴─────┐
              │  120Ω     │
              │  终端电阻  │
              └───────────┘

这里有几个关键点:

  • 总线两端必须各接一个120Ω终端电阻。这是为了消除信号反射。我见过有人偷懒不接终端电阻,结果总线上的信号波形乱七八糟,通信距离稍微远一点就出错。
  • 节点通过CAN收发器连接到总线。收发器负责把逻辑电平转换成差分信号。常用的收发器有TJA1050、SN65HVD230等。
  • 总线长度受波特率限制。比如125kbps时,总线最长可以到500米;1Mbps时,最长只有40米左右。这是由信号传播延迟决定的。

实战建议:在Zephyr RTOS里配置CAN时,一定要在设备树里正确设置波特率和终端电阻。我习惯在开发板上先测一下总线波形,用示波器看看CAN_H和CAN_L的差分电压是不是在2V左右。如果波形有振铃或者过冲,那多半是终端电阻没配好。

1.5 总结:CAN总线基础,你该记住什么?

好了,咱们把这一章的核心内容捋一捋:

  1. CAN的诞生:为了解决汽车线束过多、可靠性差的问题,博世在1986年推出。
  2. 物理层:差分信号,CAN_H和CAN_L,显性电平2V,隐性电平0V。
  3. 差分信号原理:共模抑制,抗干扰能力强,适合恶劣环境。
  4. 拓扑结构:多主总线,两端必须接120Ω终端电阻。

下一章咱们会深入CAN的数据链路层,聊聊帧格式、仲裁机制和错误处理。到时候我会结合Zephyr RTOS的CAN驱动,给大家演示实际代码怎么写。嗯,今天就到这儿,有问题随时问我。