3、CAN总线入门:从历史到物理层,我踩过的那些坑

大家好,我是你们的嵌入式老司机。今天咱们聊聊CAN总线。

说实话,CAN总线是我入行时接触的第一个“正经”工业总线。那时候我刚从学校出来,以为串口就是一切。直到第一次看到CAN总线的差分信号波形,我才意识到——原来通信还能这么玩。

3.1 CAN总线的发展历史:一个德国人的倔强

CAN总线,全称Controller Area Network。1986年,德国博世公司搞出来的。

为什么会有CAN?说白了,当时汽车里的线束太多了。你想想看,一个豪华车,各种传感器、执行器、控制器,全用点对点连线。那线束比你的胳膊还粗,成本高、重量大、故障率还高。

博世的工程师们想:能不能搞一条总线,把所有设备都挂上去?于是CAN诞生了。

我记得我第一次看到CAN总线的原始论文时,心里想的是:这帮德国人真严谨。协议栈设计得滴水不漏,连最微小的错误场景都考虑到了。

关键时间节点:

  • 1986年:博世公司提出CAN总线概念
  • 1991年:发布CAN 2.0规范(A/B两部分)
  • 1993年:ISO 11898标准发布
  • 2003年:CAN FD(灵活数据速率)开始研发
  • 2012年:CAN FD正式发布

现在,CAN总线早已不局限于汽车。工业自动化、医疗设备、航空航天、甚至你家的电梯里,都有它的身影。

3.2 CAN总线特点:为什么它这么能打?

我经常跟新人说:CAN总线能活30多年,不是没有道理的。它的设计哲学,放到今天依然先进。

3.2.1 多主从结构

传统总线,比如RS-485,是主从结构。主机不问你,从机就不能说话。

CAN不一样。任何节点都可以随时发起通信。谁先抢到总线,谁就说话。这就是所谓的“多主从”。

我在项目中遇到过一个问题:一个传感器节点突然发疯,疯狂往总线上发数据。如果是RS-485,整个系统就瘫痪了。但CAN总线有仲裁机制,优先级高的报文照样能发出去。嗯,这就是设计上的冗余。

3.2.2 非破坏性位仲裁

这是CAN最牛的地方之一。

当两个节点同时发送数据时,它们不会冲突。CAN总线通过“线与”逻辑,让优先级高的报文自动获胜。优先级低的节点检测到总线被占用,就乖乖退出发送。

你想想看,这多高效。不像以太网,冲突了还得重传。

我的经验:仲裁机制依赖“显性位”和“隐性位”。显性位(逻辑0)会覆盖隐性位(逻辑1)。所以,报文ID越小,优先级越高。设计系统时,把紧急报文ID设小一点,比如0x001给刹车,0x100给车窗。

3.2.3 错误检测与自动重发

CAN总线有5种错误检测机制:位错误、填充错误、CRC错误、格式错误、应答错误。

一旦检测到错误,发送节点会自动重发。而且,如果某个节点错误太多,总线会把它“隔离”掉,不让它影响其他节点。

我曾经调试过一个设备,总线上老是出现莫名其妙的错误帧。查了半天,发现是一个节点的晶振频率偏差太大。CAN总线对时钟精度要求很高,这一点后面会细说。

3.2.4 实时性与确定性

CAN总线的报文传输时间是确定的。因为它的仲裁机制是确定性的,不会出现随机退避。

这一点对汽车安全至关重要。刹车信号必须在规定时间内到达,不能因为总线拥堵就延迟。

特性 CAN总线 RS-485 以太网
拓扑结构 多主从 主从 多主从
仲裁方式 非破坏性位仲裁 CSMA/CD(冲突检测)
实时性
错误处理 自动重发+节点隔离 需软件处理 重传+退避
最大节点数 110个(理论) 32个(典型) 无限制

3.3 CAN总线物理层:差分信号才是灵魂

很多人学CAN,只关注协议层。但我跟你说,物理层才是最容易出问题的地方。

3.3.1 差分信号原理

CAN总线使用两条线:CAN_H和CAN_L。信号通过这两条线的电压差来传输。

为什么用差分?说白了,抗干扰能力强。

你想想看,如果总线上有共模噪声,两条线上的电压同时升高或降低。但它们的差值不变。所以接收端能正确解析数据。

我在一个工厂里调试过CAN总线。现场有大功率电机,电磁干扰非常严重。如果用单端信号,数据早就被淹没了。但CAN总线稳如老狗,一条数据都没丢。

3.3.2 显性位与隐性位

CAN总线的两种状态:

  • 显性位(Dominant):CAN_H比CAN_L高约2V。逻辑0。
  • 隐性位(Recessive):CAN_H和CAN_L电压差接近0V。逻辑1。

显性位会覆盖隐性位。这就是仲裁的基础。

注意:总线空闲时,所有节点都输出隐性位。如果总线上没有终端电阻,隐性位电压可能不稳定。我见过有人忘了接终端电阻,结果总线一直报错。

3.3.3 终端电阻

CAN总线两端必须各接一个120Ω的终端电阻。为什么是120Ω?因为CAN总线的特性阻抗就是120Ω。

终端电阻的作用:

  • 消除信号反射
  • 保证总线进入显性状态时的电流回路

我曾经犯过一个低级错误:在调试时,把终端电阻接到了中间节点上。结果总线信号反射严重,通信时好时坏。查了两天才发现,原来终端电阻必须放在最远端。

3.3.4 总线长度与波特率

CAN总线的通信距离和波特率成反比。波特率越高,能传的距离越短。

波特率 最大总线长度
1 Mbps 40米
500 kbps 100米
250 kbps 250米
125 kbps 500米
50 kbps 1000米

为什么会有这个限制?因为信号在总线上的传播速度是有限的。如果总线太长,信号还没传到远端,下一个位就已经发送了。这会导致位采样错误。

我建议:在项目初期就确定好通信距离和波特率。别等到布线完了才发现信号质量不行。

3.3.5 共模电压范围

CAN收发器能承受的共模电压范围是-2V到+7V(ISO 11898标准)。

如果共模电压超出这个范围,收发器可能损坏。我在一个项目中,CAN总线跟大功率设备共地,结果地线压差达到了10V。收发器烧了好几个。

解决方案:使用隔离型CAN收发器,或者加共模扼流圈。

避坑指南:

  • 终端电阻必须接在总线两端,不是中间
  • 总线长度不要超过波特率对应的最大值
  • 注意共模电压,必要时加隔离
  • CAN_H和CAN_L不要接反,否则通信失败
  • 总线拓扑尽量用直线型,不要用星型或环型

3.4 小结:CAN总线入门,从物理层开始

CAN总线入门,我建议你先从物理层开始。把差分信号、终端电阻、总线长度这些搞明白,后面学协议层就轻松多了。

下一章,我们会深入CAN总线的数据链路层,看看报文是怎么组织的。到时候我会分享一个我调试CAN总线时遇到的“幽灵报文”案例,保证让你大开眼界。

记住:做嵌入式,动手比看书重要。找两块开发板,接上CAN收发器,自己搭一个最小系统试试。相信我,踩过的坑才是你的经验。