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收发器,自己搭一个最小系统试试。相信我,踩过的坑才是你的经验。