错误检测和管理

在总线上发送或者接收数据时,若通信节点检测到错误,会主动发起错误帧。前面章节介绍到错误帧除了发送 6Bit 的错误标志外,可能会有 0 ~ 6 Bit 的错误标志重叠的情况。在介绍错误帧之前,首先需要了解 ISO 11898 标准中的位填充、错误类型及错误处理机制。

位填充 (Bit Stuffing)

ISO 11898 协议中规定,信号同步方式依赖于信号的边沿跳变,如果数据流中连续出现大量相同的逻辑电平(例如连续的 '1' 或连续的 '0'),会导致信号长时间不翻转。接收端此时将无法同步,导致采样点漂移,通信出错。 为解决上述问题,需要进行位填充,具体规则如下:

  • 发送节点逻辑:在发送数据帧和远程帧时,在 SOF ~ CRC 字段内检测到连续 5 个相同极性的位时,会在其后自动插入一个极性相反的填充位(Stuff Bit)。

  • 接收节点逻辑:在接收数据帧和远程帧时,在 SOF ~ CRC 字段内解码数据流时,如果检测到连续 5 个相同极性的位,会自动剔除(De-stuff)随后的那一个相反极性的位,从而恢复原始数据。如果第 6 为位电平和前 5 位相同,则视为填充错误。

示意图如下,填充标志位用橘色色块标记:

../../../_images/can_bit_stuff.png

位填充示意图

错误类型

常见的错误类型如下表所示:

错误类型汇总及错误帧发送时机

错误种类

错误原因

错误的检测范围

错误帧发送时机

检测单元

位错误

比较输出电平和总线电平(不含填充位),当两电平不一样时所检测到的错误。

  • 数据帧(SOF ~ CRC)

  • 远程帧(SOF ~ CRC)

  • 错误帧标志位

  • 过载帧标志位

下一位期间

(在检测到位错误的位之后,立即开始发送错误标志)

发送单元

填充错误

在需要位填充的段内,连续检测到 6 位相同的电平时所检测到的错误。

  • 数据帧(SOF ~ CRC 序列)

  • 远程帧(SOF ~ CRC 序列)

下一位期间

(在检测到第 6 个连续相同位的时刻,立即开始发送错误标志)

接收单元

CRC 错误

从接收到的数据计算出的 CRC 结果与接收到的 CRC 序列不同时所检测到的错误。

  • 数据帧(CRC 序列)

  • 远程帧(CRC 序列)

ACK 界定符之后

(在 ACK 界定符位之后,即 EOF 的第一位位置开始发送)

接收单元

格式错误

检测出与固定格式的位段相反的格式时所检测到的错误。

  • 数据帧/远程帧

    (CRC 界定符、ACK 界定符、 EOF 前 6Bit )

  • 错误界定符

  • 过载界定符

下一位期间

(例外:如果是在 CRC 界定符检测到的格式错误,看作 CRC 错误,在 ACK 界定符后发送)

发送单元

接收单元

ACK 错误

发送单元在 ACK 槽 (ACK Slot) 中检测出隐性电平时所检测到的错误(未收到接收节点的 ACK 显性电平 0)。

  • 数据帧(ACK 槽)

  • 远程帧(ACK 槽)

ACK 界定符之后

(在 ACK 界定符位之后,即 EOF 的第一位位置开始发送)

发送单元

错误帧发送时机:

  1. 立即发送 (Next Bit):

    位错误、填充错误、格式错误(绝大多数情况)一旦被检测到,节点会在下一位立即破坏当前传输,发送错误帧。这保证了数据的一致性,防止错误的扩散。

  2. 延迟发送 (After ACK Delimiter):

    CRC 错误和 ACK 错误是在 ACK 界定符之后才发送错误帧。

    • CRC 错误: 接收节点虽然在 CRC 校验阶段就算出了错误,但它不会立即报错,而是会先发送一个 ACK(如果格式正确),或者不发送 ACK,等到 ACK 界定符结束后,才在 EOF 阶段拉低总线报错。这样做是为了不破坏其他可能正确接收到数据的节点的 ACK 过程。

    • ACK 错误: 发送节点发现没人应答(ACK Slot 为隐性),它会在 ACK 界定符之后发送错误帧。

备注

  • 位错误不会发生在 ID 仲裁段、 ACK 槽以及发生被动错误时:

    • ID 仲裁阶段如果发送 1 但是收到 0,则认为仲裁丢失

    • ACK 槽位,发送端发送隐性电平 1,读回时仍然是 1,表明未收到应答

    • 节点发送被动错误标志(连续 6bit 隐性位),却回读到显性位,不认为是位错误。

  • 在 EOF 最后 1 bit 出现显性位,发送过载帧,而不是错误帧。

  • 发送节点的产生错误一般有:位错误、格式错误、ACK 错误

  • 接收节点的产生错误一般有:填充错误、格式错误、CRC 错误

错误处理机制

当 CAN 通信节点检测到错误时,根据内部错误计数器(TEC 和 REC)的数值变化,会在以下三种状态之间自动切换。

../../../_images/can_error_state.svg

错误状态跳转

备注

  • TEC: 发送错误计数器 (Transmit Error Counter)

  • REC: 接收错误计数器 (Receive Error Counter)

下表总结了各状态的进入条件及行为特性。

CAN 总线错误状态详解

错误状态

进入条件 (阈值)

错误标志类型

通信与行为特性

主动错误

(Error Active)

TEC ≤ 127 且

REC ≤ 127

主动错误标志

(6 个连续显性位)

  • 正常通信:节点全速参与总线发送与接收。

  • 强干预:检测到错误时,立即发送显性电平破坏总线数据,通知全网。

被动错误

(Error Passive)

TEC > 127 或

REC > 127

被动错误标志

(6 个连续隐性位)

  • 弱干预:检测到错误时发送隐性位,若总线正处于显性状态,该标志会被覆盖(即无法破坏总线),不影响其他主动错误节点通信。

  • 发送延迟:连续发送两帧数据之间,必须额外插入 8 个隐性位的“挂起(Suspension)传输时间”。

总线关闭

(Bus Off)

TEC > 255

无

(禁止发送)

  • 通信禁止:节点逻辑上与总线断开,物理层驱动器关闭。

  • 恢复机制:需执行复位序列或检测到总线 128 次空闲(11 个连续隐性位)才可恢复为主动错误状态。

错误计数器的变动在检测到错误标志的 第一位 时触发,一次数据发送/接收可能同时满足多个条件,错误计数值可能被多次调整。下表列出了计数规则变动条件:

TEC 与 REC 计数规则

序号

触发条件

TEC

REC

1

接收器检测到错误(在发送主动错误标志或过载标志期间检测到的位错误除外)。

—

+1

2

接收器在发送错误标志后,检测到的第一个位为显性位。

—

+8

3

发送器发送错误标志。

+8

—

4

发送器在发送主动错误标志或过载标志期间检测到位错误。

+8

—

5

接收器在发送主动错误标志或过载标志期间检测到位错误。

—

+8

6

任何节点在发送错误标志或过载标志后,检测到过量的连续显性位:

  • 发送主动错误/过载标志后检测到连续 14 个显性位;

  • 或发送被动错误标志后检测到连续 8 个显性位;

  • 以及随后每额外增加 8 个连续显性位。

+8

+8

7

发送器成功发送一帧(成功获得 ACK 并且直到 EOF 完成都没有错误)。

若 > 0 则 -1;

若 = 0 则不变

—

8

接收器成功接收一帧(在 ACK 槽之前无错误,且成功发送显性 ACK 位)。

—

若 1 ≤ REC ≤ 127,则 -1;

若 = 0,则不变;

若 > 127,置为 119 ~ 127 之间

10

总线关闭恢复(检测到 128 次 × 11 个连续隐性位)

置 0

置 0

第三种情况存在例外:

  1. 发送器处于被动错误状态,因 ACK 槽未检测到显性位产生 ACK 错误,且在发送被动错误标志时未检测到显性位。

  2. 发送器因仲裁期间的填充错误发送错误标志(除非该违规位本应是隐性但被监测为显性,此时 TEC 仍增加 8)。

发送错误帧

  1. 错误标志未重叠:下图 错误标志未重叠 展示了节点 A 发送时检测到“位错误”,然后节点 B 检测到连续 6 个相同的显性电平产生“填充错误”,此时总线上节点 A 的错误标志位和节点 B 的错误标志位并未重叠

../../../_images/can_error_flag_normal.svg

错误标志未重叠

  1. 错误标志重叠:下图 错误标志重叠 展示了节点 A 产生了“位错误”,节点 B 检测到连续 6 个相同的显性电平,产生填充错误。两个节点的主动错误标志重叠 2 位,剩下部分还有 4 位。

../../../_images/can_error_flag_overlap.svg

错误标志重叠

发送过载帧

过载帧的标志位是连续 6Bit 的显性电平 0,会破坏总线上其他节点的发送过程,导致其他节点不能正常发送报文,变相推迟了其他节点的发送。 以下三种情况下需要发送过载帧:

  • 接收节点内部未就绪:接收节点由于自身处理速度限制或缓冲区限制,尚未准备好接收下一帧数据,会在帧间隔(Intermission)的第一位发送过载帧,强行拉长空闲时间。

  • 接收节点在帧间隔(Intermission)的第 1 位或第 2 位检测到显性位 :正常的帧间隔应至少包含 3 个连续的隐性位。若在前两位出现显性位,通常意味着有节点提前发送了报文(时序错误)或总线出现了干扰。此时节点会发送过载帧来处理这种异常同步。

  • 接收节点在错误界定符 (Error Delimiter) 或 过载界定符 (Overload Delimiter) 的 第 8 位(最后一位)检测到了显性位 (Dominant, 0):界定符的标准格式是 8 个连续的隐性位。如果在最后一位检测到显性位,被视为下一帧报文过早开始(或者前一帧未能正确结束)。在这种特定情况下触发的过载帧,不会增加节点的错误计数器。

  • 帧结束 (EOF) 最后一位检测到显性位 :由于 EOF 前 6 位已通过检查,协议判定 当前帧接收有效 (Valid),不作为格式错误处理。

备注

  • 错误计数器:过载帧的发送是“无害”的,它 不会 增加节点的发送错误计数器 (TEC) 或接收错误计数器 (REC)。

  • 数量限制:为了防止总线被永久阻塞,控制器通常限制连续发送过载帧的次数(通常最多允许 2 帧延时)。