1. 从沙子到车辙:为什么一个做底层的人要死磕CAN总线
“从沙子到车辙”这个系列名字本身就带着一股执拗劲儿——从最原始的硅砂开始,一路讲到车轮压过的痕迹。前面几篇聊过芯片制造、PCB布局、电源设计,到了4.3这个节点,话题终于落在了CAN总线和CAN-FD上。说实话,如果你是一个做嵌入式或者汽车电子的人,看到这两个词大概率会心一笑:终于讲到通信了。
CAN(Controller Area Network)这东西,1983年由博世提出,1986年正式发布,到现在四十多年了,依然是汽车电子和工业控制领域最坚挺的现场总线之一。为什么?因为它简单、可靠、抗干扰强,而且成本低到令人发指。你随便拆开一辆车,从发动机控制单元到车窗升降模块,从电池管理系统到仪表盘,几乎所有的ECU之间都在用CAN或者它的衍生版本通信。而CAN-FD(Flexible Data-rate)则是2012年博世推出的升级版,核心解决的就是经典CAN带宽不够用的问题。
这篇文章不是教科书式的协议讲解,而是从一个实际做过多个车载项目的从业者角度,把CAN和CAN-FD从物理层到应用层的坑一个一个挖出来。我会讲清楚:为什么经典CAN的1Mbps上限成了瓶颈,CAN-FD怎么在保持兼容性的前提下把数据段速率拉到5Mbps甚至更高,实际布线时终端电阻到底怎么选,采样点怎么算,以及那些只有真正调过总线波形的人才会知道的细节。如果你正在做车载控制器、BMS、电机驱动器或者任何需要多节点可靠通信的项目,这篇内容应该能帮你省下不少调试时间。
2. 经典CAN的底层逻辑:为什么它能在恶劣环境里活下来
2.1 差分信号与显性隐性:物理层的生存哲学
CAN总线最核心的物理层设计就是差分信号。两根线,CAN_H和CAN_L,平时都处于约2.5V的隐性状态(逻辑1),当发送显性位(逻辑0)时,CAN_H被拉到约3.5V,CAN_L被拉到约1.5V,差分电压约2V。接收端不看绝对电压,只看两根线的压差。这个设计的好处是:发动机点火、电机PWM开关、继电器吸合产生的共模干扰,会同时耦合到两根线上,压差保持不变,数据就不会出错。
我实测过在电机驱动器旁边走CAN线,不加共模电感的情况下,用示波器看单端波形简直是灾难,但差分探头一看,眼图依然清晰。这就是差分传输的威力。但注意,前提是两根线必须紧密双绞,绞距越短越好,通常建议每米33绞以上。如果只是随便并排走,共模抑制能力会急剧下降。
显性位覆盖隐性位是CAN仲裁机制的物理基础。当两个节点同时发送时,谁先发出显性位谁就获得总线控制权。这个机制叫CSMA/CR(载波侦听多路访问/冲突解决),不是CSMA/CD那种检测到冲突就退避,而是非破坏性仲裁——优先级高的报文继续发,优先级低的自动转为接收,没有任何数据被浪费。这也是CAN适合实时控制系统的根本原因。
2.2 帧结构与位填充:那些容易忽略的细节
经典CAN帧分标准帧(11位ID)和扩展帧(29位ID)。一个标准数据帧的结构是:SOF(1位显性)、仲裁段(11位ID + RTR)、控制段(IDE + r0 + DLC)、数据段(0-8字节)、CRC段(15位CRC + 分隔符)、ACK段(ACK槽 + 分隔符)、EOF(7位隐性)。看起来简单,但有几个地方特别容易踩坑。
位填充是第一个坑。CAN协议规定,在SOF到CRC序列之间,每连续5个相同极性的位之后,必须插入一个相反极性的位。接收端会自动删除这个填充位。这个机制是为了保证接收端能持续进行位同步。但如果你用逻辑分析仪抓波形,看到的数据流和实际报文内容是不一样的,必须经过解码才能还原。我见过有新手直接拿示波器读位流,怎么算CRC都对不上,就是没考虑位填充。
DLC与实际数据长度是第二个坑。经典CAN的DLC是4位,取值0-8,但如果你发送DLC=9到15,实际数据长度仍然是8字节,但接收端可能会报格式错误。有些控制器在DLC大于8时会直接丢弃帧。所以在写驱动的时候,DLC字段一定要严格等于实际发送的字节数。
ACK槽是第三个坑。发送节点在ACK槽发送隐性位,任何正确接收的节点都会拉低总线变成显性位。如果发送节点在ACK槽采样到隐性,说明没有任何节点接收成功,会触发ACK错误。这个机制在单节点测试时特别烦人——你一个节点自己发自己收,没有其他节点给ACK,发送会一直失败。解决办法要么接一个能正常通信的节点,要么把控制器设成自测模式(Loopback),内部自己给ACK。
2.3 位定时与采样点:1Mbps不是随便就能跑的
CAN的位定时由四个段组成:同步段(Sync_Seg)、传播段(Prop_Seg)、相位缓冲段1(Phase_Seg1)、相位缓冲段2(Phase_Seg2)。采样点位于Phase_Seg1结束的位置。采样点位置的计算公式是:
采样点 = (Sync_Seg + Prop_Seg + Phase_Seg1) / (Sync_Seg + Prop_Seg + Phase_Seg1 + Phase_Seg2) × 100%
对于1Mbps的经典CAN,位时间通常是1μs。常见的配置是:Sync_Seg=1Tq,Prop_Seg=2Tq,Phase_Seg1=3Tq,Phase_Seg2=2Tq,总位时间8Tq,采样点在75%。这个75%是CiA推荐的默认值,但实际项目中要根据总线长度和节点数量调整。
总线长度和波特率有直接关系。信号在双绞线上的传播速度大约是5ns/m,一个来回就是10ns/m。如果总线长40米,来回传播延迟就是400ns。在1Mbps下,位时间是1000ns,传播段必须能覆盖这个延迟。所以Prop_Seg至少要设置到400ns以上。这就是为什么1Mbps的CAN总线长度通常限制在40米以内,而125kbps可以跑到500米。
我见过一个项目,总线长度大概35米,节点有12个,1Mbps死活通信不稳定,偶尔丢帧。后来用示波器测采样点,发现配置成了87.5%,而实际总线延迟导致边沿已经偏移了。把采样点调到75%并增加Prop_Seg后,问题消失。所以采样点不是随便设的,必须根据总线物理参数计算。
3. CAN-FD的进化逻辑:不只是把速度拉高那么简单
3.1 为什么需要CAN-FD:经典CAN的天花板
经典CAN的最大问题是带宽。1Mbps的波特率,一帧最多8字节数据,加上协议开销(约47位),实际有效数据率大概只有50%左右。算一笔账:一帧标准数据帧总长度约111位(含位填充),在1Mbps下需要111μs。如果每秒发1000帧,数据量就是8000字节,约64kbps的有效载荷。这在现代汽车里完全不够用。
举个例子,一个电池管理系统有96个电芯,每个电芯的电压、温度需要上报,假设每个电芯4字节数据,一轮就是384字节。如果分48帧发送(每帧8字节),在1Mbps下需要约5.3ms。如果BMS要求10ms上报一次,总线负载率就超过50%了。再加上电机控制器、整车控制器、仪表等其他节点的通信,总线很容易过载。
CAN-FD的核心思路是:仲裁段保持经典CAN的速率以保证兼容性和仲裁可靠性,数据段切换到更高的速率。仲裁段用1Mbps,数据段可以到2Mbps、5Mbps甚至8Mbps。同时数据长度从8字节扩展到64字节。这样一帧可以传更多数据,协议开销占比大幅下降。
3.2 帧格式变化:FDF、BRS、ESI三个关键位
CAN-FD帧在经典CAN帧的基础上增加了几个控制位。在控制段中,IDE位之后是FDF(FD Format)位,显性表示经典CAN,隐性表示CAN-FD。然后是res位和BRS(Bit Rate Switch)位,BRS为显性时数据段不切换速率,为隐性时切换到更高的数据速率。最后是ESI(Error State Indicator)位,显性表示发送节点处于错误主动状态,隐性表示错误被动状态。
CRC段也变了。经典CAN是15位CRC,CAN-FD根据数据长度使用17位或21位CRC,并且增加了CRC分隔符和填充计数。这是因为数据段速率提高后,位错误概率增加,需要更强的校验。
还有一个重要变化是位填充规则。CAN-FD在仲裁段仍然使用每5位插入填充位的规则,但在数据段(BRS为隐性时)使用固定的填充模式,每4位插入一个填充位。这是为了在高速下保持同步的稳定性。
3.3 速率切换的物理实现:收发器与时钟的要求
CAN-FD对收发器的要求比经典CAN高得多。经典CAN收发器如TJA1050,上升沿和下降沿的对称性要求没那么严格。但CAN-FD在5Mbps下,位时间只有200ns,收发器的传播延迟、上升/下降时间、对称性都会直接影响采样。所以必须使用支持CAN-FD的收发器,比如TJA1044、TJA1051、MCP2562FD等。
时钟源也很关键。CAN-FD控制器的时钟通常需要40MHz或80MHz,以支持高分辨率的时间量子(Tq)。如果使用内部RC振荡器,温漂和老化会导致采样点偏移,高速下必然出错。所以必须使用外部晶振,精度至少±0.5%,最好±0.1%。
我实测过用某款MCU的内部RC振荡器跑CAN-FD 2Mbps,常温下勉强能通,一到85℃就大量丢帧。换成外部晶振后,-40℃到125℃全温区稳定。这个坑值得所有人注意。
4. 从原理图到波形:CAN-FD硬件设计的实操要点
4.1 终端电阻与拓扑:120Ω不是随便放的
CAN总线两端各需要一个120Ω终端电阻,这是常识。但实际项目中,我见过太多人把终端电阻放错位置,或者阻值不对。终端电阻的作用是匹配总线特性阻抗,消除信号反射。双绞线的特性阻抗通常是120Ω左右,所以两端各接120Ω,并联后总线等效阻抗60Ω。
如果终端电阻放在中间节点,或者只放一个,信号反射会导致波形振铃,高速下直接通信失败。我见过一个项目,四个节点,终端电阻放在了第二个节点上,1Mbps还能凑合,500kbps以下没问题,但一上2Mbps CAN-FD就大量错误帧。后来把电阻移到物理两端,问题解决。
还有一个常见错误是终端电阻的功率。120Ω在显性状态下消耗的功率是(2V)^2/120Ω ≈ 33mW,看起来很小,但如果总线经常处于显性状态(比如连续发送),电阻会发热。0603封装电阻的额定功率通常是100mW,够用但余量不大。建议用0805或1206封装,留足余量。
拓扑方面,CAN总线必须是手拉手的菊花链结构,不能星型或树型。分支长度越短越好,通常建议分支不超过0.3米。如果必须分支,分支点要尽量靠近主干,且分支上的节点要少。我见过一个项目用星型拓扑,四个节点从中心点各拉一根线,结果2Mbps下完全无法通信。改成菊花链后立刻正常。
4.2 共模电感与TVS:保护与信号的平衡
共模电感在CAN接口上很常见,作用是抑制共模干扰。但选型有讲究。共模电感的阻抗在100MHz下通常选100Ω到200Ω,差模阻抗要低,否则会影响信号质量。我见过有人用了差模阻抗过大的共模电感,导致CAN-FD 5Mbps下信号边沿变缓,采样出错。
TVS管用于防静电和浪涌。选型时要注意结电容。普通TVS的结电容可能几百pF,在5Mbps下会严重衰减信号。必须选低电容TVS,结电容小于10pF,最好小于5pF。比如PESD1CAN、NUP2105等专用CAN保护器件。
还有一个细节是共模电感和TVS的放置顺序。从连接器进来,先TVS后共模电感,还是先共模电感后TVS?我的经验是:先TVS,把高压浪涌钳位掉,再进共模电感。如果反过来,浪涌可能直接打坏共模电感。当然,如果空间允许,两级保护更好。
4.3 PCB布局:差分对走线与阻抗控制
CAN_H和CAN_L必须等长、平行、紧耦合走线。差分阻抗控制在120Ω。如果走线长度超过10cm,建议做阻抗计算。我用过四层板,CAN差分对走在内层,参考平面完整,阻抗控制得很好。如果是两层板,差分对走在顶层,底层铺地,阻抗会偏高,需要调整线宽和间距。
差分对之间的间距要尽量小,通常建议小于2倍线宽。但也不能太小,否则制造时蚀刻偏差会导致阻抗不一致。一般线宽0.2mm,间距0.2mm,在1.6mm厚的FR4上,差分阻抗约120Ω。具体数值要用阻抗计算工具确认。
还有一个容易忽略的点是过孔。差分对上的过孔会引入阻抗不连续,高速下产生反射。如果必须换层,两个过孔要对称放置,且尽量靠近。我通常建议CAN差分对不要换层,如果实在要换,最多换一次。
5. 软件配置与调试:从寄存器到波形的完整链路
5.1 位定时参数计算:以5Mbps数据段为例
假设MCU的CAN时钟是80MHz,CAN-FD控制器的时间量子Tq = 1/80MHz = 12.5ns。对于5Mbps数据段,位时间是200ns,需要16个Tq。分配如下:Sync_Seg=1Tq,Prop_Seg=2Tq,Phase_Seg1=7Tq,Phase_Seg2=6Tq。采样点 = (1+2+7)/16 = 62.5%。
等等,62.5%是不是太早了?对于CAN-FD数据段,由于速率高,传播延迟占比小,采样点可以适当提前。CiA 601-4推荐数据段采样点在60%-70%之间。62.5%是合理的。但仲裁段仍然用1Mbps,位时间1000ns,80MHz下是80Tq。分配:Sync_Seg=1Tq,Prop_Seg=16Tq,Phase_Seg1=40Tq,Phase_Seg2=23Tq,采样点 = (1+16+40)/80 = 71.25%。接近75%,合理。
实际配置时,很多MCU的CAN-FD控制器允许分别设置仲裁段和数据段的位定时。比如STM32的FDCAN模块,有NBTP(Nominal Bit Timing)和DBTP(Data Bit Timing)两组寄存器。配置时要仔细计算,确保采样点在推荐范围内。
5.2 过滤器配置:别让无关报文占用CPU
CAN控制器的过滤器是硬件资源,配置好了可以大幅降低CPU负载。经典CAN通常有14-28个过滤器组,CAN-FD控制器可能更多。过滤器的配置逻辑是:每个过滤器组可以设置一个ID和掩码,匹配的报文才会被接收并产生中断。
我见过一个项目,把所有报文都接收,然后在软件里判断ID。结果总线负载率30%的时候,CPU有40%的时间在处理CAN中断。后来把过滤器配好,只接收需要的ID,CPU负载降到5%以下。
CAN-FD的过滤器还支持范围过滤和双ID过滤。范围过滤可以接收一个ID区间内的所有报文,双ID过滤可以同时匹配两个不同的ID。灵活使用这些功能,可以进一步减少软件开销。
5.3 错误处理与总线恢复:Bus-Off不是世界末日
CAN控制器有错误计数器:发送错误计数器(TEC)和接收错误计数器(REC)。当TEC超过255时,节点进入Bus-Off状态,自动脱离总线。这是CAN的自我保护机制,防止一个故障节点持续干扰总线。
Bus-Off后,节点需要等待128次连续11个隐性位,才能重新接入总线。这个过程叫总线恢复。如果故障未排除,节点会反复进入Bus-Off,导致通信时断时续。
我在实际项目中遇到过Bus-Off,排查下来是终端电阻虚焊,导致反射严重,错误帧频发。修复焊点后,Bus-Off不再出现。所以遇到Bus-Off,第一反应应该是查物理层,而不是改软件。
软件上,可以配置Bus-Off自动恢复,也可以手动恢复。自动恢复适合无人值守的场景,手动恢复适合需要记录故障信息的场景。我通常建议开启自动恢复,同时在软件里记录Bus-Off次数,用于诊断。
6. 常见问题与排查技巧实录
6.1 通信不稳定:从物理层到协议层的排查顺序
通信不稳定是最常见的问题,排查要遵循从物理层到协议层的顺序。第一步,用示波器看波形。差分探头看CAN_H和CAN_L的差分信号,检查显性电平是否达到2V,隐性电平是否在0V附近,边沿是否干净。如果波形有振铃,查终端电阻和拓扑。如果边沿太缓,查共模电感和TVS。
第二步,用CAN分析仪抓报文。看错误帧类型:位错误、填充错误、CRC错误、格式错误。位错误通常是采样点不对或波特率不匹配。填充错误通常是位填充规则被破坏,可能是干扰导致。CRC错误说明数据在传输中变了,通常是物理层问题。
第三步,查节点配置。所有节点的波特率和采样点必须一致。我见过一个项目,两个节点的采样点一个75%一个87.5%,500kbps下勉强能通,1Mbps下大量错误帧。统一采样点后解决。
6.2 CAN-FD速率切换失败:BRS位与收发器延迟
CAN-FD速率切换失败的表现是:仲裁段正常,数据段报错。常见原因是收发器的对称性不够。CAN-FD收发器有一个参数叫环路延迟对称性,要求小于±10ns。如果收发器不满足,数据段高速下采样会偏移。
还有一个原因是BRS位配置错误。有些MCU的CAN-FD控制器需要单独使能BRS,如果没使能,数据段仍然用仲裁段速率,但发送端以为切换了,接收端没切换,就会出错。检查寄存器配置,确保BRS使能。
我实测过某款国产CAN-FD收发器,2Mbps下正常,5Mbps下误码率很高。换用国际大厂的收发器后,5Mbps稳定。所以高速CAN-FD对收发器品牌和型号很敏感,选型时要看数据手册的对称性参数。
6.3 总线负载率计算与优化
总线负载率是衡量CAN网络健康度的重要指标。计算公式是:
负载率 = (所有报文每秒钟占用的位时间总和) / 1秒
对于经典CAN,一帧标准数据帧约111位(含位填充),扩展帧约131位。对于CAN-FD,仲裁段用经典CAN速率,数据段用高速率,要分别计算。
我通常建议负载率控制在30%以下,最高不超过50%。超过50%后,低优先级报文的延迟会显著增加,实时性无法保证。如果负载率过高,优化手段包括:合并报文(用CAN-FD的64字节)、提高波特率、减少不必要的报文、调整报文周期。
我做过一个项目,负载率65%,导致刹车信号偶尔延迟超过10ms。后来把BMS的电压报文从10ms改成20ms,负载率降到45%,刹车延迟恢复正常。所以负载率优化是系统工程,要抓主要矛盾。
6.4 常见问题速查表
| 现象 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| 完全无法通信 | 终端电阻缺失或阻值错误 | 万用表测总线电阻,应为60Ω | 两端各接120Ω |
| 通信时断时续 | 终端电阻虚焊或拓扑分支过长 | 示波器看波形振铃 | 重焊电阻,改菊花链 |
| 高速下大量错误帧 | 采样点不一致或收发器不匹配 | 查各节点位定时配置 | 统一采样点,换FD收发器 |
| Bus-Off频繁 | 物理层干扰或错误帧累积 | 查TEC/REC计数器 | 修复物理层,开启自动恢复 |
| CAN-FD数据段报错 | BRS未使能或收发器延迟大 | 查BRS寄存器,测收发器对称性 | 使能BRS,换低延迟收发器 |
| 负载率过高 | 报文过多或周期太短 | 用分析仪统计负载率 | 合并报文,降低频率 |
7. 一些只有调过波形才懂的实操心得
第一个心得:示波器一定要用差分探头。单端探头看CAN波形,共模干扰会让你怀疑人生。差分探头虽然贵,但能省下大量排查时间。如果实在没有差分探头,可以用两个单端探头做数学运算,但精度和共模抑制比差很多。
第二个心得:CAN分析仪要选支持CAN-FD的。很多老款分析仪只支持经典CAN,接上CAN-FD总线要么不识别,要么报错。我用的分析仪支持CAN-FD,能自动识别帧类型并解码,调试效率高很多。
第三个心得:终端电阻可以用可调电阻箱临时替代。调试阶段,不确定终端电阻是否匹配时,用可调电阻箱从100Ω到150Ω扫一遍,看哪个阻值下波形最干净。确定后再换成固定电阻。这个方法我用了很多次,特别适合非标线缆的项目。
第四个心得:CAN-FD的64字节数据段不是越多越好。数据段越长,CRC计算时间越长,错误帧重传的代价越大。如果实际数据只有20字节,没必要凑到64字节。按需分配,兼顾效率和可靠性。
第五个心得:总线上的节点数不是越多越好。每个节点都会引入电容和漏电流,节点越多,总线负载越重,信号边沿越缓。经典CAN通常建议不超过30个节点,CAN-FD高速下建议不超过15个。如果节点多,可以用CAN网关分段。
第六个心得:温度对CAN-FD的影响比经典CAN大。高温下收发器的延迟会增加,采样点会偏移。所以CAN-FD的采样点要留足够的余量,通常建议比理论值偏后一点,比如65%而不是60%。我在-40℃和125℃都测过,采样点65%时全温区稳定。
第七个心得:软件上要加总线错误统计。每个节点的TEC、REC、Bus-Off次数、错误帧类型,都记录下来。这些数据在排查偶发问题时非常有用。我通常会在软件里做一个环形缓冲区,记录最近100次错误事件,出问题时直接导出分析。
第八个心得:CAN-FD的兼容性要提前确认。不是所有经典CAN节点都支持CAN-FD。如果总线上混有经典CAN节点,CAN-FD节点发送FD帧时,经典CAN节点会报格式错误,可能触发错误帧。解决办法是:要么全部升级到CAN-FD,要么CAN-FD节点在发送时先检测总线上的经典CAN节点,避免冲突。实际项目中,我通常建议全网络统一升级,混跑太痛苦。
第九个心得:线缆选择不能凑合。CAN总线要用屏蔽双绞线,屏蔽层单点接地。我见过用普通排线跑CAN的,1Mbps下勉强能通,但EMC测试直接挂掉。换成屏蔽双绞线后,辐射发射和抗扰度都轻松通过。线缆的 characteristic impedance 要是120Ω,线径建议0.5mm²以上,长距离时用0.75mm²。
第十个心得:调试阶段先降速。新板子第一次调CAN,不要直接上1Mbps或5Mbps。先用125kbps或250kbps跑通,确认物理层和基本通信正常,再逐步提速。这样能把物理层问题和协议层问题分开,排查效率高很多。我见过新手直接上1Mbps,通信失败后不知道是硬件问题还是软件问题,折腾了好几天。
8. 从沙子到车辙:CAN-FD之后还有什么
写到这里,CAN和CAN-FD的核心内容基本覆盖了。从物理层的差分信号、终端电阻、拓扑结构,到协议层的帧格式、位定时、过滤器,再到实操中的波形调试、错误排查、负载率优化,这些都是实际项目中绕不开的环节。
CAN-FD之后,车载网络还在往更高带宽走。CAN XL正在制定中,目标是20Mbps以上,数据段更长。车载以太网也在普及,100BASE-T1、1000BASE-T1在域控制器和摄像头、雷达之间用得越来越多。但CAN和CAN-FD不会消失,因为它们的成本、可靠性和生态是其他总线无法替代的。车身控制、电池管理、电机控制这些对带宽要求不高但对可靠性要求极高的场景,CAN-FD仍然是最优解。
我个人在实际操作中的体会是:CAN总线的调试,80%的问题在物理层,20%在协议层。把终端电阻、拓扑、线缆、收发器这些基础打牢,软件配置只要按手册计算,基本不会出大问题。反过来,如果物理层有隐患,软件再怎么调都是治标不治本。所以每次新项目,我都会先花时间把CAN的物理层设计和测试做扎实,后面调试就轻松很多。
最后再分享一个小技巧:用CAN分析仪的统计功能做长期监测。把分析仪接在总线上,跑24小时,统计错误帧率、负载率、最大延迟。这些数据比单次抓包更有价值,能发现偶发问题和趋势性变化。我通常会在项目小批量试产阶段做这个测试,提前发现潜在问题,避免量产后的批量故障。