做车载嵌入式这几年,如果说哪条总线是“生命线”,我第一个想到的就是CAN。这个系列从芯片内部的寄存器一路聊到整车通信,到了4.3这一篇,正好是CAN和CAN-FD。文章定位给正在做ECU开发、测试标定,或者刚从单片机转到车载方向的工程师看。读完你会理解一条报文从节点发出到另一个节点收下,中间经过了哪些机制,以及CAN-FD为什么能带着更高的带宽继续在车上跑很多年。
1. 为什么汽车电子还在用 CAN:物理层设计的基本盘
1.1 两根差分线如何扛住整车电磁环境
CAN的物理层看起来非常简单,一对双绞线,两个120欧姆终端电阻,没了。但恰恰是这套看起来简单的方案,从几十年前一直用到了现在。关键在“差分”这两个字。
总线空闲时,CAN_H和CAN_L都维持在2.5V左右,差分电压接近0V,这叫隐性电平。节点发送显性位时,CAN_H被拉到3.5V以上,CAN_L被拉到1.5V以下,差分电压大约2V。接收端真正关心的不是CAN_H或者CAN_L对地的绝对电压,而是两根线之间的差值。
整车环境里有电机、继电器、点火线圈这些强干扰源,它们产生的共模噪声会同时叠加在两根线上。既然接收端只认差值,共模噪声自然就被抵消掉了。双绞线又进一步保证两根线受到的电磁干扰尽量一致,这就是CAN能在发动机舱这种恶劣环境里稳定工作的根本原因。
单端总线比如UART,把地作为参考电平,一旦干扰源把地电位抬起来,接收端就会误判。CAN的物理层从一开始就避开了这个坑。实际做台架测试时,我见过总线旁边过一个大电流负载,CAN波形上叠了十几伏的毛刺,通信依然正常,换成单端总线早就乱码了。这种抗干扰能力是靠物理层设计赢来的,不是软件上打补丁能追回来的。
1.2 多主仲裁:没有总控也能排队
CAN的第二个反直觉设计,是总线上没有主节点。所有ECU都可以随时往总线上发数据,想发就发,不需要等谁同意。那多个节点同时发怎么办?靠逐位仲裁。
CAN的显性电平在电气上会“盖过”隐性电平。每个发送节点都是边发送边监听总线,一旦发现总线上的电平比自己发出去的电平更“强势”,就说明有更高优先级的节点在同时发送,自己立刻退出发送,变成接收者。这个仲裁过程按位进行,一个字节一个字节地比,直到只剩一个节点占据总线。
仲裁用的优先级就是帧ID。ID数值越小,二进制里0出现得越早,显性电平越靠前,优先级越高。所以CAN-ID的规划直接影响整车通信的实时性。安全气囊报文、制动报文这种对延迟敏感的,ID要分配得很靠前;车窗、空调这类舒适性报文,ID就算靠后一点,晚个几十毫秒也没有人感知得到。这属于网络设计阶段就要定清楚的规则,不能等代码写完再想。
整车架构里用到CAN-FD之后,仲裁段速率上限依然和经典CAN保持一致,也是为了一方面保证多节点公平仲裁,另一方面让总线拓扑和节点设计不需要因为速率提升而重新做一套。物理层背后的逻辑是自洽的。
1.3 总线形态对比:CAN / LIN / 车载以太网
不是所有地方都需要高速通信,车上的总线选型其实是一个成本、带宽、确定性综合权衡的结果。我之前整理过一张对比表,给新接手项目的同事看特别直观。
| 总线 | 典型速率 | 成本 | 拓扑 | 实时性 | 主要用途 |
|---|---|---|---|---|---|
| LIN | 20kbps | 很低 | 单主多从 | 差 | 车窗、雨刮、车内灯 |
| 经典CAN | 最高1Mbps | 低 | 多主总线 | 好 | 动力、车身、诊断 |
| CAN-FD | 数据段可达5Mbps以上 | 低 | 多主总线 | 好 | 固件升级、高带宽数据传递 |
| 车载以太网 | 100Mbps起 | 较高 | 星型/环型 | 较好 | ADAS、摄像头、娱乐系统 |
值得强调的是,CAN家族到今天还没有被淘汰,是因为它的确定性和可靠性优势在动力和底盘域太关键了。以太网确实带宽高,但交换式架构带来的时延抖动、PoDL供电、线束成本,都不是小数目。CAN-FD的出现恰好把经典CAN的带宽瓶颈补上了一部分,又保留了CAN的成熟生态,很多新平台选择它作为主干网络是有道理的。
2. 一帧经典 CAN 报文到底是怎么运转的
2.1 帧格式逐字段拆解
很多初学者拿到一帧CAN数据,看到的是一串十六进制数,比如ID 0x1A0,Data 01 02 03 04 05 06 07 08,但这串数字背后有完整的帧结构在约束它。
标准数据帧的字段顺序是:SOF(1位显性)、11位ID、RTR、IDE、保留位、DLC、数据场、CRC场、ACK场、EOF。ID决定了优先级和报文身份;RTR用来区分数据帧还是远程帧,数据帧为显性0,远程帧为隐性1;IDE用来区分标准帧还是扩展帧;DLC是数据长度编码,经典CAN下0到8直接对应0到8个字节。
扩展帧则把ID从11位扩到29位,结构里多出了SRR位和IDE位,其它字段基本一致。实际工程里标准帧用于大多数控制类报文,扩展帧多用于诊断、标定这类需要大量ID空间的场景。诊断协议里最常见的是扩展帧。
我在教组里新人时,喜欢让TA们先手动解析一次波形,把示波器截下来的每一位都标出来。这么做一次之后,字段表就再也不会忘。贴一个标准帧的字段说明表:
| 字段 | 长度 | 作用说明 |
|---|---|---|
| SOF | 1位 | 帧起始,显性,标志总线从空闲进入忙碌 |
| 标识符 ID | 11位标准 / 29位扩展 | 报文身份与仲裁优先级 |
| RTR | 1位 | 远程帧标志,隐性为请求远程数据 |
| IDE | 1位 | 0为标准帧,1为扩展帧 |
| 保留位 | 1或2位 | 固定为显性,为CAN-FD预留扩展空间 |
| DLC | 4位 | 数据长度编码 |
| 数据场 | 0-8字节 | 有效载荷 |
| CRC | 15位 | 循环冗余校验,覆盖起始到数据场 |
| ACK | 2位 | 发送方发隐性,接收方拉显性应答 |
| EOF | 7位 | 帧结束,全部为隐性 |
2.2 位填充与CRC:错误概率压到多低
CAN有一个很多人不在意的机制,叫位填充。规则是发送端如果在总线上连续输出了5个相同电平的位,就必须在第6个位插入一个反相位的填充位。接收端在收到5个连续相同位之后,会检查第6位是否与预期相反,如果不对,直接判定为格式错误。
位填充的第一个作用是为接收节点的PLL提供足够的时钟沿。不管是哪个速度的CAN,位同步都依赖波形上的边沿跳变,一段长时间没有沿,收发器内部的采样时钟就无法校准,误码率会明显上升。第二个作用是让总线上的信号能量分布更均匀,降低电磁发射。
CRC15给一帧最多8字节的数据提供校验,配合位填充和应答机制,未检出的错误概率被压到很低的水平。更关键的是,CAN的错误发现不是靠某一个节点单独判断,而是所有节点都在监听,任何节点发现错误,都会主动发出错误帧,把出错的报文从总线上“抹掉”,然后发送节点重新发送。这种集体监督机制,是很多点对点总线做不到的。
2.3 用一条报文走一遍收发流程
假设节点A想发送一条ID为0x1A0的报文。它先等待总线空闲,然后从SOF开始,一位一位往总线上放数据。如果此时节点B也在发一条ID更小的报文,仲裁就会发生,ID大的A节点会在仲裁段检测到总线电平比自己的强,主动退出,等下一轮再抢总线。
节点A完整发完一帧之后,所有正常接收的节点会在ACK槽把总线拉成显性,作为对发送端的“收到”确认。这里有个坑:CAN收发器在发送时,接收路径拿到的电平其实是自己发出去的电平。所以发送节点无法靠回环判断其它节点是不是真的收到了,必须靠ACK槽里有没有其它节点发出的显性位。如果总线上只有一个节点,ACK槽就是隐性的,发送节点会raise一个应答错误。这也是为什么单独一台ECU接在总线上时,哪怕它一直在发报文,协议分析仪也看不到错误,但把分析仪挂上去,错误帧就出来了——因为这时才有人应答它。
之后每个接收节点会做ID过滤、DLC检查、CRC校验。都通过了,数据才算“被收到”。哪一步不满足,该节点就会送出一个错误帧,避免把错误数据用进控制逻辑里。
3. CAN-FD 到底改了哪些东西
3.1 三大变化:可变速率、64字节、更强的 CRC
CAN-FD全称CAN with Flexible Data-rate,核心变化是三个:数据段速率可以切换、数据长度可以到64字节、CRC和错误检测能力更强。
经典CAN的数据段和仲裁段都是同一个速率,最高1Mbps。CAN-FD则在帧格式里增加了一个BRS位,控制着数据段是否切到更高的速率。仲裁段仍然保持经典速率,保证多个节点可以公平仲裁;确认数据段用高速传输,快速搬运大块数据。
数据场的DLC编码也变了,不是线性关系。DLC值0到8对应0到8字节,9对应12字节,10对应16字节,11对应20字节,12对应24字节,13对应32字节,14对应48字节,15对应64字节。写代码时经常有人直接把DLC填成想在数据场发送的字节数,结果数据长度不符合预期,就是没搞清楚这张映射表。
CRC方面,经典CAN固定用15位多项式,CAN-FD按帧长使用17位或21位的CRC,数据段还引入了填充位计数。高数据率下位时间更短,同样长度报文被干扰的概率变高,更强的CRC是必要补偿。CAN-FD另一点改进是数据段不再做传统逐位填充,而是改为在固定位置插入固定填充位,通过填充位计数参与CRC校验,既能避免高速率下填充规则带来的开销浪费,又能维持足够的跳变沿来同步。
经典CAN和CAN-FD的差异,最核心的都在下面这张表里:
| 特性 | 经典CAN | CAN-FD |
|---|---|---|
| 仲裁段速率 | 最高1Mbps | 最高1Mbps |
| 数据段速率 | 同仲裁段 | 最高可达5Mbps以上,常用2-5Mbps |
| 数据长度 | 最多8字节 | 最多64字节 |
| CRC | 15位 | 17位或21位 |
| 帧类型 | 标准帧/扩展帧 | 标准FD帧/扩展FD帧 |
| 兼容性 | 广泛 | 与经典CAN不能在同一网络混用 |
3.2 速率切换为什么难:BRS 位与 TDC
BRS位看起来很简单,一位切换速率,但工程上最常踩的坑刚好在这。发送节点从仲裁段的500kbps切到数据段的2Mbps或5Mbps,总线上的信号位宽瞬间缩小,接收节点能不能在正确的时间点采样,被两个细节决定。
第一个是采样点配置。数据段位时间比仲裁段短,如果沿用仲裁段的CLK分频和TSEG配置,采样点会偏得离谱。所以CAN-FD控制器必须独立配置仲裁段和数据段两套位时间参数。第二个是收发器和线缆的传输延迟。数据段速率越高,一个位的时间越短,比如2Mbps时一个位才500ns,收发器内部的环路延迟有时就能占掉十分之一甚至更多。高速采样时,接收节点如果还用固定的采样点,可能刚好采到电平切换的“抖动区”。
控制器厂商普遍给出的方案是TDC(Transmitter Delay Compensation,发送延迟补偿)。原理是控制器自己测量从发送到总线返回信号的延迟,然后把数据段采样点往后推到真正稳定的区域。TDC通常涉及一个测量窗口和偏移配置,很多控制器还提供“次级采样点”机制。实际调CAN-FD网络时,如果数据段速率超过2Mbps,TDC不是你调不调的问题,而是必须调准,不然就会出现“低速全对,高速CRC全错”的怪现象。
为什么仲裁段不也跟着提速?仲裁需要所有节点都能同时收到每一位才能保证公平,而高速段的传输延迟会让距离远的节点来不及完整参与仲裁。所以CAN-FD只对真正传数据的数据段提速,仲裁段保持经典速率,这是协议设计里很务实的取舍。
3.3 兼容与混用:FD 和经典 CAN 能不能同网
这个问题几乎每个项目初期都会有人问。CAN-FD帧报文在经典CAN节点看来是格式违规的,因为FDF位、BRS位这些字段在经典CAN帧里根本不存在,经典节点无法解析FD帧,会直接触发错误帧,把总线上正常的FD通信搅乱。反过来,经典CAN帧在CAN-FD节点里可以正常接收,因为CAN-FD控制器通常是向下兼容经典CAN的。
结论是同一个物理网络上,不能一部分节点发FD帧、一部分节点只发经典CAN帧。要么全网都是CAN-FD,要么就都用经典CAN。如果有新老平台混用的需求,只能通过网关在两种网络之间做转换,网关节点把经典CAN帧转发成CAN-FD帧,或者反过来。网关方案会让数据多一次转发延迟,但总比让两边硬扯在一起好。
从项目规划角度,哪怕系统初期只跑经典CAN报文,只要MCU选型支持CAN-FD,网络拓扑、终端电阻、线束设计要求就按CAN-FD来设计。等后续需要升级固件或增加大数据量报文时,硬件不用动,只改配置就够。这是我建议很多团队提前做的事。
4. 从沙子到车辙:一个 CAN-FD 节点的设计落地细节
4.1 硬件链路怎么搭
CAN节点的硬件链路从内到外大致是MCU的CAN控制器、外部收发器、共模电感、保护器件和连接器。芯片内部控制器负责协议层;收发器负责把控制器送出的TX信号转成总线上的差分电平。选择收发器时,除了速率,还要看EMC等级和是否支持CAN-FD的快速斜率控制。数据段跑5Mbps时,普通慢斜率收发器的边沿根本跟不上,必须选专门支持高速FD的型号。
共模电感放在收发器和连接器之间,主要滤除共模干扰,对CAN来说几乎是标配。ESD保护二极管和TVS管也尽量靠近连接器,否则从线束进来的静电和浪涌会直接打在收发器上。总线两端各放一个120欧姆终端电阻,很多评估板把电阻做在板上,实际量产节点通常只在拓扑的两个物理末端放,中间节点一般不焊终端电阻。一个常见的误操作是把每个节点都当终端节点,导致总线上并联了多个120欧,等效阻抗变小,信号反射变大,还削弱了差动信号幅度。
如果网络比较长或分支节点较多,可以考虑使用分裂终端,即两个60欧姆电阻串联后中间接一个4.7nF电容到地。这种接法在不破坏终端匹配的前提下,给共模噪声提供一个低阻抗路径,EMC测试里经常能帮上忙。代价是比单个120欧电阻多两个器件,但对于整车这种长线束场景很值得。
4.2 位时间与采样点配置:手把手算一遍
位时间配置是所有CAN开发人员绕不开的步骤。以某款MCU的CAN-FD控制器为例,假设外设时钟CANCLK是80MHz,仲裁段目标速率500kbps,数据段目标速率2Mbps。
首先明确CAN位时间的组成:同步段(SS)固定为1个时间量子(TQ),传播段加相位缓冲段1合起来常叫TSEG1,相位缓冲段2叫TSEG2。一个位的总长度是1 + TSEG1 + TSEG2。采样点位置在同步段和TSEG1结束之后,也就是 (1 + TSEG1) / (1 + TSEG1 + TSEG2)。
仲裁段500kbps,一个位的时间是2微秒。如果预设分频器Prescaler取10,TQ就是125纳秒,那么位时间需要16个TQ。取TSEG1=12,TSEG2=3,采样点就是(1+12)/16=81.25%。这个采样点对500kbps来说是合理的,多数控制器默认推荐在80%到87.5%之间。
数据段2Mbps,一个位的时间是500纳秒。如果Prescaler取5,TQ是62.5纳秒,位时间需要8个TQ。取TSEG1=5,TSEG2=2,采样点就是(1+5)/8=75%。数据段速率比仲裁段快,采样点通常会略低一点,给信号建立留出余量。
配置代码可以是这样:
canfd_bit_timing_t nom = { .prescaler = 10, // 80MHz / 10 = 8MHz TQ .tseg1 = 12, // 传播段+相位缓冲段1 .tseg2 = 3, // 相位缓冲段2 .sjw = 1, // 同步跳转宽度 }; // 位时间16TQ => 500kbps, 采样点81.25% canfd_bit_timing_t dat = { .prescaler = 5, // 80MHz / 5 = 16MHz TQ .tseg1 = 5, // 传播段+相位缓冲段1 .tseg2 = 2, // 相位缓冲段2 .sjw = 1, }; // 位时间8TQ => 2Mbps, 采样点75%不同厂商的寄存器字段名可能不同,但计算逻辑完全一致。配置完以后,不要只依赖配置工具,自己拿计算器算一遍采样点,再决定是否启用TDC。很多项目出问题,根源就是某一次改时钟频率之后,Prescaler没有同步更新,位时间全变了。
4.3 示波器上看什么
CAN信号质量的判断,必须回归示波器。我常用的方法是把示波器探头一边接CAN_H,一边接CAN_L,用差分方式测量,带宽至少比总线速率高5倍以上。500kbps的仲裁段,几十兆带宽就够;看5Mbps的数据段,带宽至少要到100MHz级别,不然边沿都被滤没了。
先看隐性电平和显性电平的绝对值。CAN_H隐性应该在2.5V附近,显性抬升到3.5V左右;CAN_L隐性2.5V,显性被拉到1.5V左右。两线差分信号的幅度通常在2V左右。如果显性差分幅度明显偏低,优先怀疑终端电阻并联过多或者收发器驱动能力不足。如果波形上过冲、振铃特别严重,说明阻抗不连续,通常出在分支线太长、终端位置不对或者线缆不规范上。
再用示波器的总线解码功能直接解出报文和错误帧。握手触发、ID过滤,这些功能不同品牌的仪器差别很大,但通用的思路是一致的:先确认波特率配置是否和预期一致,再确认采样点位置。很多示波器可以显示采样点位置,直接和配置的百分比对一下,立刻能看出问题。CAN-FD调试还要观察BRS位之后的波形,确认数据段边沿质量确实达标,而不是只在仲裁段看了个大概。
5. 现场高频问题与排查技巧
5.1 Bus-Off 和错误帧风暴
Bus-Off是所有CAN开发人员都会遇到的噩梦。节点发送错误计数累积超过255,控制器会自动进入Bus-Off状态,不再参与总线通信,看起来就像“死”了一样。最常见的触发原因是两个节点波特率不一致,导致收发双方对位的理解不同;其次是终端电阻缺失、信号反射过大,导致接收节点采样到的电平错误;还有一种情况是ID冲突,两个节点在同一时刻发同一条ID,仲裁机制认为格式错误,反复进错误帧。
排查时先断开疑似有问题的节点,看总线是否恢复。再用协议分析仪统计总线上错误帧的ID和频率,错误帧往往固定在某个节点往外的方向,顺着线束查过去的成功率很高。用手动触发一台节点发一条测试报文,配合示波器看波形,是区分物理层问题和协议层问题最快的方式。
Bus-Off恢复策略也要提前设计好。有的控制器支持自动恢复,错误消失后自动重新参与总线;有的必须由应用层调用恢复接口。整车项目中,Bus-Off频繁自动恢复可能引发总线反复被干扰,需要在软件里增加恢复延迟甚至掉电重启策略,这些在需求阶段就要和系统工程师对齐。
5.2 终端电阻与布线问题
终端电阻看起来简单,实际上是现场出问题最多的位置。整车线束在装配过程中,偶尔会出现某个节点被误当成端节点、把终端电阻也焊上的情况。此时两个120欧并联变成60欧,总线信号幅值整体下降,距离远的节点开始在临界值附近反复误判。
还有一种情况是只在一端接了终端电阻,另一端空着,波形反射严重,示波器上能看到振铃。排查方式很直接:断开总线电源,用万用表在任意位置量CAN_H和CAN_L之间的直流电阻。正常情况下应该是60欧左右(两个120欧并联),如果测出来是120欧,说明有一端没接;如果明显小于60欧,说明不止两个终端电阻。
布线方面,最怕的是把CAN线和其他大电流线绑得太近。CAN虽然抗共模干扰,但线束间的容性耦合还是会把强干扰引进来。双绞线的作用是让两根线受到的耦合尽量一致,一旦车间装配时为了省事用平行线替代,双绞的意义就没了。遇到这类问题,看得见的整改在软件,看不见的源头在线束。
5.3 CAN-FD 数据段 CRC 失败
CAN-FD网络最常见的高速率故障现象是:仲裁段通信正常,一旦数据段切到2Mbps以上,接收节点频繁报CRC错误或格式错误。这不是数据被干扰了,而是时序余量不足。
原因是数据段位时间太短,收发器和线缆的环路延迟占比过高,接收节点的固定采样点落在了不稳定区间。解决思路有三个:第一,开启并校准TDC,让采样点自动贴近真实信号中心;第二,把数据段速率从5Mbps降到2Mbps,换取更宽松的位时间;第三,缩短分支线长度,减少反射累积。如果TDC已经打开还是报错,用示波器对比发送端和接收端的波形,重点看BRS位切换后的第一个数据位,那里往往能看到边沿塌陷。
还有一个容易被忽略的点,是总线上混入了只支持经典CAN的收发器。有些老收发器在数据段高速率时带宽不够,边沿被拉长,虽然没有完全报错,但信号质量明显变差。CAN-FD设计选型时,收发器必须明确标称支持5Mbps,不能拿经典CAN收发器顶替。
5.4 排查工具与流程速查表
多年的现场经验,让我养成了一个习惯:通信问题先分层,再动手。
| 现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 所有节点都收不到 | 总线无显性电平 / 波特率不符 | 示波器看波形幅度;逐个节点断电排除 |
| 偶发错误帧 | 终端电阻问题 / 线束干扰 | 量终端电阻;收线束;观察错误帧触发时机 |
| 单节点Bus-Off | 该节点违规 / 收发器损坏 | 断开该节点看总线;更换收发器验证 |
| CAN-FD高速率CRC失败 | TDC未校准 / 采样点配置偏差 | 校准TDC;降低数据段速率;看BRS后波形 |
| 唤醒失败 | 网络管理报文未收到 / 收发器待机电流异常 | 示波器抓总线电平;检查收发器模式引脚 |
排查流程上,我个人的习惯是“先物理后协议,先单点后全网”。物理层问题没有排除干净之前,做多少协议层分析都是白费功夫。有时候问题很玄,台上测试全通过,装到整车上就报错,这种时候优先怀疑线束走向和地电位差异,而不是纠结配置参数。
最后再分享一个特别有用的调试习惯:在样件阶段就预留一组CAN调试接口,最好能直接跨接示波器或逻辑分析仪,不要等到问题出现了再去找线束上的测试点。一条完整的总线,加上两端和中间若干可测量的接口,能让你在排查时至少少走一半弯路。CAN-FD到来之后,这个习惯的价值只增不减,因为数据段高速率下,你看到的波形细节直接决定了能不能找到根因。