4. CAN总线错误处理:错误类型与状态机
大家好,我是老周。今天咱们聊一个硬核话题——CAN总线的错误处理。说实话,我见过太多工程师在调试CAN总线时,一看到错误帧就慌了神。其实,只要你理解了CAN的错误机制,定位问题就像看地图一样清晰。
CAN总线为什么可靠?说白了,就是因为它有一套非常完善的错误检测和处理机制。这套机制保证了即使在一个节点出问题的情况下,整个网络依然能正常工作。嗯,这里咱们先看看CAN定义了哪几种错误类型。
4.1 五种错误类型
CAN协议规定了五种错误类型。我个人习惯把它们分成两类:传输错误和协议错误。咱们一个一个来看。
| 错误类型 | 检测层级 | 检测节点 | 触发条件 |
|---|---|---|---|
| 位错误 | 物理层 | 发送节点 | 发送位与总线电平不匹配 |
| 填充错误 | 数据链路层 | 所有节点 | 连续6个相同电平 |
| CRC错误 | 数据链路层 | 接收节点 | CRC校验不通过 |
| 形式错误 | 数据链路层 | 所有节点 | 固定格式位电平错误 |
| 应答错误 | 数据链路层 | 发送节点 | ACK槽未收到显性位 |
4.1.1 位错误
位错误是最基础的一种错误。发送节点在发送一个位的同时,会监控总线上的实际电平。如果发现不一致,就判定为位错误。
举个例子:你发送了显性位(0),但总线上却是隐性位(1)。为什么会这样?可能是总线短路了,或者另一个节点同时发送了相反的位。
我在项目中遇到过一件事:一个节点总是报位错误,查了半天发现是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槽仍然是隐性,就报应答错误。
应答错误的含义很明确:没有节点收到你的报文。可能是总线断了,可能是波特率不匹配,也可能是总线上只有一个节点。
4.2 错误状态机
光检测到错误还不够,CAN协议还定义了一套错误状态机,用来管理节点的行为。每个节点都有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。
根据这两个计数器的值,节点处于三种状态之一:
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会迅速飙升。这就是为什么一个坏节点能很快被"踢出"总线。
4.4 错误处理的实际应用
在实际项目中,我一般这样利用错误信息定位故障:
- 看错误类型:位错误和应答错误指向发送节点,CRC错误和填充错误指向接收节点或总线质量。
- 看错误频率:偶尔一次可能是干扰,持续出现就是硬件问题。
- 看节点状态:如果某个节点频繁进入错误被动状态,先检查它的CAN收发器和电源。
- 看总线波形:用示波器抓CANH和CANL的差分信号,看电平是否正常,边沿是否陡峭。
我记得有一次,一个现场总线总是间歇性通信中断。我远程登录到设备上,读取了所有节点的TEC值,发现有一个节点的TEC高达200多。顺着这个线索查下去,发现是那个节点的CAN总线线缆被老鼠咬破了,屏蔽层接地不良。
嗯,这就是CAN错误处理的精髓。理解了这五种错误类型和状态机,你就能像老中医一样,通过"望闻问切"快速定位总线故障。下次咱们聊聊如何用示波器抓取和分析错误帧,那才是真正的实战。