4. CAN总线错误处理:错误类型与状态机

大家好,我是老周。今天咱们聊一个硬核话题——CAN总线的错误处理。说实话,我见过太多工程师在调试CAN总线时,一看到错误帧就慌了神。其实,只要你理解了CAN的错误机制,定位问题就像看地图一样清晰。

CAN总线为什么可靠?说白了,就是因为它有一套非常完善的错误检测和处理机制。这套机制保证了即使在一个节点出问题的情况下,整个网络依然能正常工作。嗯,这里咱们先看看CAN定义了哪几种错误类型。

4.1 五种错误类型

CAN协议规定了五种错误类型。我个人习惯把它们分成两类:传输错误和协议错误。咱们一个一个来看。

错误类型 检测层级 检测节点 触发条件
位错误 物理层 发送节点 发送位与总线电平不匹配
填充错误 数据链路层 所有节点 连续6个相同电平
CRC错误 数据链路层 接收节点 CRC校验不通过
形式错误 数据链路层 所有节点 固定格式位电平错误
应答错误 数据链路层 发送节点 ACK槽未收到显性位

4.1.1 位错误

位错误是最基础的一种错误。发送节点在发送一个位的同时,会监控总线上的实际电平。如果发现不一致,就判定为位错误。

举个例子:你发送了显性位(0),但总线上却是隐性位(1)。为什么会这样?可能是总线短路了,或者另一个节点同时发送了相反的位。

注意:在仲裁场和ACK槽中,位错误不会被触发。因为仲裁时多个节点同时发送是正常行为,ACK槽本来就是等待接收节点拉低。

我在项目中遇到过一件事:一个节点总是报位错误,查了半天发现是CAN收发器的TX和RX引脚焊反了。你想想看,发送的数据被自己接收回来,当然对不上。

4.1.2 填充错误

CAN协议规定:连续发送5个相同位后,必须插入一个相反位的填充位。如果任何节点检测到连续6个相同电平,就报填充错误。

这个机制是为了保证总线有足够的电平跳变,方便接收节点同步时钟。我曾经调试过一个设备,它在高温下频繁报填充错误。后来发现是晶振温漂太大,导致位时序偏移,接收节点采样点跑偏了。

4.1.3 CRC错误

每个CAN帧都包含一个15位的CRC校验码。接收节点会重新计算CRC,如果与发送的CRC不一致,就报CRC错误。

CRC错误通常意味着总线干扰严重,或者节点时钟精度太差。我记得有一次,一个客户说他们的设备在电机启动时总丢数据。我让他们抓了总线波形,发现CRC错误帧频繁出现。最后定位到是电机驱动器产生的共模干扰耦合到了CAN总线上。

4.1.4 形式错误

CAN帧中有一些固定格式的位,比如CRC界定符、ACK界定符、EOF等。这些位必须是隐性电平。如果检测到显性电平,就报形式错误。

形式错误比较少见。我遇到过一次,是一个节点在EOF段发送了显性位,导致整个网络报形式错误。查到最后,是那个节点的CAN控制器寄存器配置错了。

4.1.5 应答错误

发送节点在ACK槽发送隐性位,然后等待接收节点拉低为显性位。如果ACK槽仍然是隐性,就报应答错误。

应答错误的含义很明确:没有节点收到你的报文。可能是总线断了,可能是波特率不匹配,也可能是总线上只有一个节点。

调试技巧:如果你看到应答错误,先检查总线终端电阻。我习惯用万用表量CANH和CANL之间的电阻,正常应该在60Ω左右(两个120Ω终端电阻并联)。

4.2 错误状态机

光检测到错误还不够,CAN协议还定义了一套错误状态机,用来管理节点的行为。每个节点都有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。

根据这两个计数器的值,节点处于三种状态之一:

CAN节点错误状态机 错误主动 TEC < 127 REC < 127 错误被动 TEC > 127 或 REC > 127 总线关闭 TEC > 255 TEC/REC 超限 TEC > 255 TEC/REC 恢复 128个隐性位恢复 关键说明: • 错误主动:正常参与通信,发送主动错误标志(6个显性位) • 错误被动:发送被动错误标志(6个隐性位),不干扰总线 • 总线关闭:完全断开与总线的连接,不发送任何数据 • 计数器规则:发送成功TEC减1,发送失败TEC加8;接收成功REC减1,接收失败REC加1

4.2.1 错误主动状态

这是正常状态。TEC和REC都小于127。节点可以正常发送和接收,检测到错误时发送主动错误标志(6个显性位)。

主动错误标志会覆盖总线上的其他数据,强制所有节点知道发生了错误。这就是CAN的"破坏性"错误通知机制。

4.2.2 错误被动状态

当TEC或REC超过127时,节点进入错误被动状态。此时节点仍然可以通信,但检测到错误时只能发送被动错误标志(6个隐性位)。

被动错误标志不会干扰总线。说白了,就是"我出错了,但我悄悄告诉你,不吵到别人"。我调试过一个设备,它在错误被动状态下发送的报文经常被其他节点忽略,因为接收节点认为它不可靠。

关键区别:错误主动节点发送显性错误标志,会破坏当前帧;错误被动节点发送隐性错误标志,不会破坏当前帧。

4.2.3 总线关闭状态

当TEC超过255时,节点进入总线关闭状态。此时节点完全断开与总线的连接,不发送任何数据,也不接收任何数据。

要退出总线关闭状态,节点需要检测到128次连续的11个隐性位(即总线空闲状态)。这个过程由硬件自动完成,不需要软件干预。

我曾经遇到一个案例:一个节点频繁进入总线关闭状态,每次恢复后又很快再次关闭。最后发现是它的CAN收发器供电电压不稳,导致发送电平异常。你想想看,发送的数据总是不对,TEC当然蹭蹭往上涨。

4.3 错误计数器的增减规则

理解计数器的增减规则,对定位问题非常有帮助。我整理了一个表格:

事件 TEC变化 REC变化
发送成功 -1 不变
发送失败(位错误/应答错误) +8 不变
接收成功 不变 -1
接收失败(CRC错误/填充错误/形式错误) 不变 +1
检测到主动错误标志 +8 +1
检测到被动错误标志 +8 +1

注意看,发送失败一次加8,发送成功一次才减1。这意味着如果一个节点持续发送失败,TEC会迅速飙升。这就是为什么一个坏节点能很快被"踢出"总线。

调试建议:如果你能读取节点的TEC和REC值,这比看错误帧数量更有用。TEC持续增长说明发送链路有问题,REC持续增长说明接收链路有问题。

4.4 错误处理的实际应用

在实际项目中,我一般这样利用错误信息定位故障:

  1. 看错误类型:位错误和应答错误指向发送节点,CRC错误和填充错误指向接收节点或总线质量。
  2. 看错误频率:偶尔一次可能是干扰,持续出现就是硬件问题。
  3. 看节点状态:如果某个节点频繁进入错误被动状态,先检查它的CAN收发器和电源。
  4. 看总线波形:用示波器抓CANH和CANL的差分信号,看电平是否正常,边沿是否陡峭。

我记得有一次,一个现场总线总是间歇性通信中断。我远程登录到设备上,读取了所有节点的TEC值,发现有一个节点的TEC高达200多。顺着这个线索查下去,发现是那个节点的CAN总线线缆被老鼠咬破了,屏蔽层接地不良。

嗯,这就是CAN错误处理的精髓。理解了这五种错误类型和状态机,你就能像老中医一样,通过"望闻问切"快速定位总线故障。下次咱们聊聊如何用示波器抓取和分析错误帧,那才是真正的实战。