1. 课程导入

各位同学,咱们今天聊聊CAN总线。说实话,这玩意儿在汽车电子圈里,就跟空气一样——平时感觉不到,但没了它,车就瘫了。

我最早接触CAN总线是在2008年,那时候给一家商用车厂做车身控制器。调试时发现,只要发动机一启动,总线上的报文就乱飞,丢帧、错位全来了。后来才明白,不是芯片不行,是我对CAN协议的理解太浅。嗯,从那以后,我养成了一个习惯:不管项目多急,先把协议基础啃透。

1.1 CAN总线起源:为什么会有它?

上世纪80年代,汽车里的电子设备越来越多。ECU、ABS、气囊、仪表盘……每个模块都用自己的线束通信。你想想看,一辆车光线束就有几十公斤重,接头上百个。故障率?高得吓人。

1986年,德国Bosch公司推出了CAN(Controller Area Network)协议。它的核心目标就三个:

  • 减少线束——所有节点挂到两根线上
  • 高可靠性——抗干扰、能检错
  • 实时性——优先级高的报文不排队

1993年,CAN成为国际标准ISO 11898。到今天,几乎每辆车上都有至少两条CAN总线——一条跑动力总成,一条跑车身控制。

核心认知:CAN不是最快的总线,也不是最便宜的。但它是在“可靠性、实时性、成本”三者之间,平衡得最好的一个。这也是它活了快40年还没被淘汰的原因。

1.2 CAN 2.0A/B标准帧格式

CAN 2.0是1991年发布的版本,分A和B两个部分。说白了,A是标准帧(11位ID),B是扩展帧(29位ID)。

我见过不少新手,上来就问“用标准帧还是扩展帧好?”我的回答是:看你的节点数量。少于20个节点,标准帧够用;超过30个,建议上扩展帧,否则ID分配会打架。

数据帧结构

一个标准CAN数据帧,长这样:

SOF | 11位ID | RTR | IDE | r0 | DLC | 0~8字节数据 | CRC | ACK | EOF

每个字段都有它的脾气:

字段 长度 说明
SOF 1 bit 帧起始,显性电平(0)
ID 11 / 29 bit 标识符,决定优先级。数值越小,优先级越高
RTR 1 bit 远程帧标志。0=数据帧,1=远程帧
DLC 4 bit 数据长度,0~8字节
Data 0~64 bit 有效载荷
CRC 15 bit 循环冗余校验,检错用
ACK 2 bit 应答槽。接收节点拉低表示收到
EOF 7 bit 帧结束,隐性电平(1)

我的经验:调试时最容易被忽略的是ACK位。如果总线上只有一个节点在发,没有其他节点应答,ACK槽会一直保持隐性。这时候发节点会认为“没人收到”,然后重发。我曾经因为这个bug,在台架上查了整整两天。

标准帧 vs 扩展帧

两者的区别,我用一张表说清楚:

对比项 标准帧 (CAN 2.0A) 扩展帧 (CAN 2.0B)
ID长度 11 bit 29 bit
最大ID数量 2048 536,870,912
帧头开销 47 bit 67 bit
总线利用率 较高 较低(多20 bit开销)
兼容性 所有CAN控制器都支持 需要CAN 2.0B控制器

我个人习惯:能用标准帧就用标准帧。只有在ID不够用,或者需要兼容J1939这类高层协议时,才切到扩展帧。

1.3 CAN FD简介

2012年,Bosch又推出了CAN FD(Flexible Data-rate)。说白了,就是给CAN提速、扩容。

CAN FD和经典CAN的区别,主要在两点:

  • 数据长度:从8字节扩展到64字节
  • 速率:数据段可以切换到更高的波特率(最高8 Mbps甚至更高)

为什么需要CAN FD?我举个例子。现在的ADAS摄像头,一帧图像数据量动辄几百字节。用经典CAN,得拆成几十帧发,延迟大、效率低。CAN FD一帧就能塞64字节,配合高速传输,效率提升明显。

注意:CAN FD和经典CAN在物理层上基本兼容,但数据链路层不兼容。也就是说,CAN FD节点可以和经典CAN节点挂在同一根总线上,但两者不能直接通信。混用时,需要做协议转换或使用兼容模式。

CAN FD的帧格式,和经典CAN类似,但多了几个标志位:

SOF | ID | BRS | ESI | DLC | 0~64字节数据 | CRC | ACK | EOF
  • BRS(Bit Rate Switch): 1表示数据段切换到高速率
  • ESI(Error State Indicator): 发送节点的错误状态

目前,CAN FD已经在高端车型上普及。我建议你在新项目里,优先考虑支持CAN FD的控制器。哪怕现在用不到,也给未来留个升级空间。

1.4 物理层特性

CAN的物理层,用的是差分信号。两根线:CAN_H和CAN_L。逻辑1是隐性(CAN_H≈2.5V,CAN_L≈2.5V),逻辑0是显性(CAN_H≈3.5V,CAN_L≈1.5V)。

为什么用差分?抗共模干扰。发动机点火、电机启停,这些强干扰源在车里到处都是。差分信号能抵消掉共模噪声,保证通信稳定。

关键参数

参数 典型值 说明
总线长度 ≤40 m @ 1 Mbps 速率越高,距离越短
终端电阻 120 Ω(两端各一个) 消除信号反射
最大节点数 30~110(取决于收发器) 受限于驱动能力
共模电压 1.5V ~ 3.5V 超出范围会丢帧

避坑指南:我曾经在一个项目中,把终端电阻焊成了120 Ω单端。结果总线反射严重,波特率降到125 kbps才能勉强通信。后来用示波器一看,信号边沿全是振铃。记住:终端电阻必须挂在总线两端,不是一端。

拓扑结构

CAN总线推荐用直线型拓扑。所有节点通过短支线(<30 cm)挂到主干上。星型、环型都不推荐,信号反射会让你怀疑人生。

下面这张图,是我画的一个典型CAN网络结构:

CAN总线典型拓扑结构 120Ω 120Ω ECU 1 ECU 2 ECU 3 ECU 4 CAN_H / CAN_L 双绞线 拓扑要点 直线型主干,支线长度 < 30 cm 两端各一个120Ω终端电阻,不可省略

1.5 小结

这一章,我们聊了CAN总线的起源、帧格式、CAN FD的升级点,还有物理层的那些坑。说白了,CAN协议并不复杂,但细节决定成败。一个终端电阻焊错位置,就能让你调一整天。