2、错误帧分类与定义:主动错误帧、被动错误帧、错误帧的构成

好,咱们接着聊错误帧。上一节我讲了错误帧是干啥的——说白了就是总线上的“报警器”。这一节咱们深入看看,这个报警器到底长什么样,分几种,每种又有什么脾气。

我个人习惯把错误帧比作交通警察的哨子。你违规了,哨子就响了。但哨子也分两种:一种是交警吹的,声音大、有威慑力;另一种是协管员吹的,声音小点,提醒你注意。嗯,CAN总线里的错误帧,就是这么回事。

2.1 主动错误帧 vs 被动错误帧

先看分类。CAN协议里,错误帧分两种:主动错误帧被动错误帧。区别在哪?说白了就是“犯错的人”当前是什么状态。

每个CAN节点内部都有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。根据这两个计数器的值,节点会处于三种状态之一:

  • 主动错误状态:TEC < 127 且 REC < 127。这是正常状态,节点可以主动发送错误帧。
  • 被动错误状态:TEC > 127 或 REC > 127。节点被“警告”了,只能发送被动错误帧。
  • 总线关闭状态:TEC > 255。节点彻底“闭嘴”,不再参与任何总线通信。

我在项目中遇到过一种情况:某个节点因为硬件干扰,TEC一路飙升到200多。它明明还在发数据,但发出来的全是被动错误帧。其他节点一看,这哥们儿不行了,纷纷给它发主动错误帧。结果整个总线乱成一锅粥。你想想看,一个“病号”拖着全车人一起遭殃。

核心区别一句话总结:

  • 主动错误帧:由主动错误状态的节点发出。它发送6个连续的显性位(主动错误标志),强势打断当前总线通信。
  • 被动错误帧:由被动错误状态的节点发出。它发送6个连续的隐性位(被动错误标志),只能“小声提醒”,无法强制打断。

2.2 错误帧的构成:错误标志 + 错误界定符

不管主动还是被动,错误帧的结构都一样——由两部分组成:错误标志错误界定符。咱们拆开看。

2.2.1 错误标志(Error Flag)

错误标志是错误帧的“核心内容”。它占6个位。但主动和被动在这6个位上表现完全不同:

类型 位值 效果
主动错误标志 6个显性位(000000) 强制覆盖总线上的任何信号,所有节点都能检测到
被动错误标志 6个隐性位(111111) 如果总线空闲,其他节点可能忽略它

这里有个关键点:主动错误标志的6个显性位,会违反CAN协议的“位填充规则”。CAN规定,连续5个相同位之后必须插入一个相反位。但错误标志故意连续发6个显性位,这就是在“故意违规”,让所有节点都意识到出事了。

我曾经调试过一个项目,发现总线上一会儿出现主动错误帧,一会儿又没了。查了半天,原来是一个节点在主动错误和被动错误之间反复横跳。它的TEC刚好卡在127附近,稍微有点干扰就过线。嗯,这种“临界状态”最坑人。

2.2.2 错误界定符(Error Delimiter)

错误标志发完之后,紧接着是错误界定符。它占8个位,全部是隐性位(11111111)。

为什么要加这个界定符?说白了就是给总线一个“冷静期”。错误标志把总线搅乱了,界定符让所有节点有时间同步回来,准备重新开始通信。

我建议你记住这个结构:

错误帧 = 错误标志(6位) + 错误界定符(8位)
主动错误标志:6位显性
被动错误标志:6位隐性
界定符:8位隐性(两者相同)

避坑指南:

我曾经犯过一个低级错误:以为错误界定符是7位。结果在写CAN控制器驱动时,时序总是差一位。查了两天手册才发现,界定符是8位,不是7位。你设计硬件或写驱动时,一定把这点刻在脑子里。

2.3 错误帧的发送时机

错误帧不是随便发的。它只在特定条件下触发:

  • 位错误:节点发送位时,监控到的总线位值与发送值不一致。
  • 填充错误:接收节点检测到连续6个相同位(违反位填充规则)。
  • CRC错误:接收节点计算的CRC与发送节点的不匹配。
  • 格式错误:帧格式中的固定位(如CRC界定符、ACK界定符)出现错误值。
  • ACK错误:发送节点在ACK槽位没有检测到显性位(没人确认收到)。

你想想看,这五种错误里,填充错误格式错误是最容易在硬件设计中被忽略的。我见过一个案例:某款MCU的CAN控制器在接收帧时,对CRC界定符的采样点设置偏了,导致偶尔把正确的帧误判为格式错误,然后疯狂发错误帧。最后整个网络瘫痪。

警告:

被动错误帧的6个隐性位,在总线空闲时可能被其他节点的显性位覆盖。这意味着被动错误帧的“威慑力”很弱。如果你的节点频繁进入被动错误状态,它基本就是在“喊救命”,但没人听得见。这时候,赶紧查硬件或软件问题,别指望它能自己恢复。

2.4 一个小例子:主动错误帧的波形

假设总线上正在传输一个数据帧,突然某个节点检测到位错误。它会立刻:

  1. 在当前位之后,立即发送6个显性位(主动错误标志)。
  2. 其他节点检测到这6个显性位(违反填充规则),也会同步发送自己的错误标志。
  3. 所有节点发送完错误标志后,一起发送8个隐性位(错误界定符)。
  4. 总线进入3位隐性位的“帧间空间”,然后重新开始仲裁。

整个过程,从错误发生到总线恢复,只需要大约十几个位时间。在500kbps的速率下,也就是几十微秒的事。这就是CAN协议健壮性的体现——快速检测、快速恢复。

我个人习惯在调试时用示波器抓一下错误帧的波形。主动错误帧那6个显性位,在波形上就是一条长长的低电平,非常显眼。如果你看到波形上频繁出现这种“长低电平”,那基本可以断定总线出问题了。

2.5 总结一下

这一节咱们把错误帧的“家底”都翻出来了:

  • 错误帧分主动被动两种,取决于节点当前的状态。
  • 结构固定:6位错误标志 + 8位错误界定符
  • 主动错误标志是显性,被动是隐性——一个能“砸场子”,一个只能“小声嘀咕”。
  • 触发条件有五种,其中填充错误和格式错误是硬件设计的常见坑。

下一节咱们聊聊错误帧对网络健壮性的影响,以及怎么在设计层面避免“错误风暴”。到时候我会分享一个我亲手踩过的坑——一个电容选型错误导致全车CAN网络崩溃的故事。嗯,那真是血的教训。