第2章:CAN总线基础:CAN协议物理层与数据链路层核心概念

好,咱们今天聊聊CAN总线。说实话,这玩意儿在车载领域太常见了。我入行那会儿,第一件事就是被师傅扔了一堆CAN协议文档,让我自己啃。当时觉得头大,后来才发现——搞懂物理层和数据链路层,你就抓住了CAN的命门。

2.1 物理层:信号怎么在线上跑

CAN总线的物理层,说白了就是两根线——CAN_H和CAN_L。它用的是差分信号传输。为什么用差分?抗干扰啊!你想想看,发动机舱里电磁环境多恶劣,单端信号早被干趴下了。

我遇到过一件事。有次台架上测CAN通信,波形老是莫名其妙地跳变。查了半天,发现是CAN_H和CAN_L的线束绞合不够紧密。嗯,这里要注意——双绞线的绞距是有讲究的,不是随便拧两下就行。

关键参数:

  • 显性电平(Dominant):CAN_H ≈ 3.5V,CAN_L ≈ 1.5V,差分电压约2V
  • 隐性电平(Recessive):CAN_H ≈ 2.5V,CAN_L ≈ 2.5V,差分电压约0V
  • 总线终端电阻:120Ω(两端各一个)

这里有个坑。显性电平会覆盖隐性电平。也就是说,只要有一个节点拉低总线,其他节点都得跟着走。这跟后面要讲的总线仲裁直接相关。

避坑指南:我曾经在项目里见过有人把终端电阻焊在PCB上,结果线束一长,信号反射得一塌糊涂。记住:终端电阻一定要放在总线物理末端,不是ECU内部随便找个位置。

2.2 数据链路层:帧结构长啥样

CAN的数据链路层,核心就是帧结构。标准帧(CAN 2.0A)有11位ID,扩展帧(CAN 2.0B)有29位ID。我个人习惯,能用标准帧就别用扩展帧——省带宽,也省CPU处理时间。

来看一个标准数据帧的结构:

SOF | 11位ID | RTR | IDE | r0 | DLC | 数据段(0-8字节) | CRC | ACK | EOF

每个字段都有它的意义:

  • SOF(Start of Frame):1位显性,告诉总线“我要发数据了”
  • ID:标识符,决定优先级。数值越小,优先级越高
  • RTR(Remote Transmission Request):区分数据帧还是远程帧
  • DLC(Data Length Code):数据长度,0到8字节
  • CRC:15位校验,加上1位隐性定界符
  • ACK:应答位,接收节点拉低表示收到

小技巧:我调试时经常用示波器抓SOF和ACK位。如果看不到ACK的显性位,说明总线上没有其他节点在听——这通常是终端电阻没接好,或者节点根本没上电。

2.3 总线仲裁:谁先说话谁有理

CAN总线没有主从节点。所有节点都能发,但同一时间只能有一个发。那冲突了怎么办?靠仲裁。

仲裁的原理很简单:ID小的优先。发送节点在发送ID位时,会同时监听总线。如果自己发的是隐性(1),但总线上是显性(0),说明有更高优先级的节点在发,自己就乖乖退出发送。

我刚开始做CAN开发时,总觉得仲裁是硬件自动处理的,不用管。直到有一次,两个ECU同时发相同ID的报文,结果总线一直冲突,系统直接卡死。后来查出来,是软件配置把两个节点的报文ID设重复了。嗯,这个坑我踩过,你们别踩。

仲裁规则总结:

  1. ID越小,优先级越高
  2. 显性位(0)覆盖隐性位(1)
  3. 仲裁失败的节点自动转为接收模式
  4. 仲裁过程不破坏数据,也不浪费带宽

2.4 位时序与同步

CAN总线的位时序,说白了就是每个bit怎么划分。一个位时间分成4段:

段名称 作用 典型长度
同步段(Sync_Seg) 检测边沿跳变 1 Tq
传播段(Prop_Seg) 补偿物理延迟 1-8 Tq
相位缓冲段1(Phase_Seg1) 采样点前调整 1-8 Tq
相位缓冲段2(Phase_Seg2) 采样点后调整 1-8 Tq

采样点通常设置在Phase_Seg1和Phase_Seg2之间。我个人习惯把采样点设在87.5%左右,也就是Phase_Seg1比Phase_Seg2长一点。为什么?因为总线传播延迟是固定的,采样点靠后能留出更多余量。

注意:不同ECU的晶振精度不一样。如果位时序配置不当,两个节点之间会出现累积误差,最终导致同步丢失。我曾经在500kbps的速率下,因为晶振偏差超过1%,总线直接罢工。解决办法是缩短采样点位置,或者用更高精度的晶振。

2.5 错误检测与处理

CAN总线有5种错误检测机制:

  • 位错误(Bit Error):发送时监听到的电平与自己发的不一致
  • 填充错误(Stuff Error):连续6个相同电平,违反位填充规则
  • CRC错误:接收方计算的CRC与发送方不一致
  • 格式错误(Form Error):固定格式位(如CRC定界符)不是隐性
  • ACK错误:发送方没收到显性应答

每个节点都有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。错误多了,节点会进入被动错误状态,甚至总线关闭状态。我见过一个极端案例——某个ECU的CAN收发器坏了,不停地发错误帧,把整个总线都拖垮了。最后只能拔掉那个节点的供电。

调试建议:用CAN分析仪看错误帧类型。如果全是CRC错误,大概率是总线干扰大。如果全是填充错误,可能是位时序没配好。如果ACK错误频繁,检查终端电阻和节点数量。

2.6 实际项目中的选型建议

最后聊点实际的。选CAN收发器时,我一般看这几个参数:

  1. 速率:125kbps到1Mbps,根据总线长度选。线越长,速率越低
  2. 共模电压范围:至少±12V,最好±27V(应对地偏移)
  3. ESD防护:HBM至少±8kV,不然产线上静电一打就挂
  4. 待机功耗:休眠模式下,电流最好小于10μA

常用的收发器有TJA1040、TJA1050、SN65HVD230这些。我个人偏爱NXP的TJA1040,皮实耐造,就是贵了点。不过车载嘛,可靠性第一,省那几毛钱不值得。

好了,CAN总线的基础就聊到这儿。物理层搞懂了线怎么走,数据链路层搞懂了帧怎么传,后面讲通信矩阵和网络管理就顺了。下一章咱们聊聊CAN的更高层协议——比如J1939和CANopen,看看它们怎么在CAN基础上搭出更复杂的应用。