云计算百科
云计算领域专业知识百科平台

CAN 总线错误处理机制详解

——从 Error Frame、TEC/REC 到 Bus-Off,彻底理解 CAN 的错误处理哲学

一、先建立一个最重要的概念

很多初学者理解 CAN 错误时,容易形成这样一个印象:

“发送节点把数据发出去,接收节点发现错误,然后通知发送节点。”

这并不是 CAN 错误处理机制的完整含义。

CAN 的设计实际上更加主动。

发送节点在发送的同时监听总线;接收节点也独立检查总线上的帧。

因此,一次 CAN 帧传输过程中:

  • 发送节点可能发现错误;
  • 一个或多个接收节点也可能发现错误;
  • 发现错误的节点可以立即发送 Error Flag;
  • 其他节点看到这个 Error Flag 后,也可能发现新的错误;
  • 多个节点发送的 Error Flag 会在总线上叠加;
  • 原来的数据帧被认为已经损坏;
  • 随后按照 CAN 的恢复机制重新发送。

ISO 11898-1 明确规定,CAN 提供错误检测、错误信号以及自动重传机制;发生错误的帧会被标记、终止,并根据恢复机制重新发送。

所以,理解 CAN Error Frame,首先要记住一句话:

CAN 不是“发现错误以后报告错误”,而是“发现错误以后立即破坏当前错误帧,并让整个网络重新开始这次通信”。


二、理解 Error Frame 之前,必须先理解 Dominant 和 Recessive

CAN 总线上只有两种逻辑状态:

  • Dominant:显性,逻辑 0
  • Recessive:隐性,逻辑 1

如果一个节点发送 Recessive,而另一个节点发送 Dominant:

总线最终表现为 Dominant。

这是 CAN 错误处理机制能够工作的物理基础。

ISO 11898-1 对这一点定义得非常明确:Dominant 表示逻辑 0,Recessive 表示逻辑 1;同时发送显性和隐性时,最终总线状态为显性。

可以简单理解成:

节点 A:Recessive 1 ─────┐
├── 总线:Dominant 0
节点 B:Dominant 0 ─────┘

因此:

Dominant 可以覆盖 Recessive。

这也是 CAN 能够实现:

  • 仲裁;
  • 错误标志;
  • 总线状态强制改变;

的根本原因。


三、CAN 为什么能够发现错误?

ISO 11898-1 规定了多种错误检测方法。

主要包括:

  • Monitoring —— 总线监视
  • Bit Stuffing / Stuff Check —— 位填充检查
  • Frame Check —— 帧格式检查
  • CRC —— 循环冗余校验
  • ACK Check —— 应答检查
  • CAN FD 还增加了 Stuff Bit Count 检查。
  • 规范明确规定了五类基本错误:

    错误类型英文谁可以发现
    位错误 Bit Error 发送节点等
    填充错误 Stuff Error 节点
    CRC错误 CRC Error 接收节点
    格式错误 Form Error 节点
    ACK错误 ACK Error 发送节点

    这些错误并不是互相排斥的,一次故障可能导致多个节点产生不同类型的错误。


    四、第一类错误:Bit Error

    4.1 什么叫 Bit Error?

    这是 CAN 错误机制中最基础的概念。

    一个节点发送某一位的时候,同时监视总线。

    如果:

    发送值 ≠ 总线实际检测值

    就可能产生 Bit Error。

    例如:

    节点 A 发送:1(Recessive)

    总线实际:0(Dominant)

    A发现:
    发送 1
    实际 0

    → Bit Error

    ISO 11898-1 的定义就是:

    发送节点把自己发送的 bit 与总线上检测到的 bit 进行比较,两者不同则检测到 Bit Error。


    五、但是有一个非常重要的例外:仲裁期间不能把它当成错误

    这是理解 CAN 最容易出现歧义的地方之一。

    假设:

    节点 A:发送 Recessive 1
    节点 B:发送 Dominant 0

    总线:Dominant 0

    A 看到:

    自己发送:1
    总线:0

    看起来完全符合:

    “发送值 ≠ 总线值”

    但此时:

    A 不认为这是 Bit Error。

    因为这可能只是:

    A 输掉了 CAN 仲裁。

    CAN 正是利用 Dominant 覆盖 Recessive 的特点实现非破坏性仲裁。

    所以:

    仲裁期间:

    发送 Recessive
    ↓
    检测到 Dominant
    ↓
    如果符合仲裁规则
    ↓
    不是错误
    ↓
    退出仲裁

    而不是:

    发送 Recessive
    ↓
    检测 Dominant
    ↓
    Bit Error

    规范明确把仲裁阶段的这种情况作为 Bit Error 的例外。


    六、第二类错误:Stuff Error

    CAN 使用 Bit Stuffing 来保证 NRZ 编码过程中有足够的边沿用于同步。

    在采用位填充的帧字段中:

    连续出现 5 个相同电平后,需要插入一个相反电平的 Stuff Bit。

    例如:

    发送:

    00000

    下一位不能继续直接发送 0,
    而应该插入:

    000001

    接收节点按照相反规则进行去填充。

    如果本来应该出现 Stuff Bit,却出现了错误的第 6 个连续相同 bit:

    000000
    ↑
    Stuff Error

    ISO 11898-1 规定:

    在采用 bit stuffing 的帧字段中,第六个连续相同电平的 bit 会被检测为 Stuff Error。


    七、第三类错误:CRC Error

    发送节点根据帧内容计算 CRC。

    接收节点收到数据后:

    重新计算 CRC
    ↓
    与收到的 CRC 比较
    ↓
    不一致
    ↓
    CRC Error

    因此 CRC Error 的本质是:

    接收节点认为“收到的内容”和发送方声明的内容不一致。

    需要注意:

    CRC Error 通常是接收节点发现的,而不是发送节点通过自己监听发现的。

    对于 Classical CAN,规范规定使用 15-bit CRC;CAN FD 根据数据长度使用 17-bit 或 21-bit CRC。


    八、第四类错误:Form Error

    CAN 帧中有一些字段具有固定格式。

    例如某些固定位置必须是:

    Dominant

    或者:

    Recessive

    如果在这些固定格式字段中出现非法 bit:

    Form Error

    例如 EOF 按规定应该是 7 个 Recessive:

    EOF:

    1 1 1 1 1 1 1

    如果出现不符合规定的 bit,就可能形成 Form Error。

    规范也规定了特殊例外,例如接收节点在 EOF 最后一个 bit 看到 Dominant,以及节点在 Error Delimiter 或 Overload Delimiter 最后一个 bit 看到 Dominant时,并不因此把它解释为 Form Error。


    九、第五类错误:ACK Error

    ACK 是 CAN 中非常特殊的一种错误。

    发送节点发送完整帧以后,在 ACK Slot 中:

    发送节点:

    ACK Slot
    ↓
    本来发送 Recessive

    正常情况下:

    至少一个正常接收节点:

    发送 Dominant

    因此:

    总线 = Dominant

    发送节点看到 Dominant:

    ACK 成功。

    如果发送节点在 ACK Slot 没有检测到 Dominant:

    ACK Error。

    规范明确规定:

    当发送节点在 ACK Slot 没有监测到 Dominant 时,检测 ACK Error。

    因此:

    ACK Error 不等于“数据内容错误”。

    它首先表示:

    发送节点没有得到 CAN 层面的确认。

    例如:

    只有一个节点:

    A → 发送 CAN 帧

    总线上没有其他正常接收节点

    ACK Slot:
    总线 = Recessive

    A:
    ACK Error

    这就是为什么:

    总线上只有一个 CAN 节点时,它发送 CAN 帧通常会不断遇到 ACK Error。

    规范的网络启动章节也明确讨论了这种情况:如果网络启动时只有一个节点在线,该节点发送帧后得不到 ACK,会检测错误并重复发送。


    十、Error Frame 到底是什么?

    CAN Error Frame(EF)由两个部分构成:

    Error Flag
    +
    Error Delimiter

    规范明确规定 Error Frame 由:

  • 不同节点产生的 Error Flag 的叠加;
  • Error Delimiter;
  • 构成。


    十一、Error Flag 有两种

    11.1 Active Error Flag —— 显性错误标志

    由:

    6 个连续 Dominant bit

    组成。

    0 0 0 0 0 0

    也就是:

    Dominant × 6

    Error-Active 节点发现错误后,就发送 Active Error Flag。


    十二、为什么 Active Error Flag 要发送 6 个 Dominant?

    因为它的目的不是“报告一个错误码”。

    它的目的实际上是:

    强制破坏当前正在传输的 CAN 帧。

    CAN 正常情况下使用 Bit Stuffing。

    连续 6 个 Dominant:

    000000

    必然破坏正常的 Stuffing 规则。

    所以其他节点也会发现:

    “当前帧已经不符合 CAN 协议规则。”

    于是它们也会进入错误处理。

    这就形成一种非常重要的效果:

    一个节点发现错误
    ↓
    发送 Active Error Flag
    ↓
    破坏当前帧
    ↓
    其他节点发现异常
    ↓
    其他节点也发送 Error Flag
    ↓
    全网共同确认:
    这帧不能用了

    ISO 11898-1 特别指出,不同节点的 Error Flag 会发生叠加,因此总线上实际观察到的连续 Dominant 序列可能是:

    最短:6 bit
    最长:12 bit

    而不是简单地认为“Error Frame 一定就是 6 个 0”。


    十三、为什么有时候示波器上看到 6~12 个 0?

    这是非常重要的工程现象。

    假设:

    A 首先发现错误

    A:
    000000

    B、C 也在不同时间检测到了这个错误。

    它们也会发送:

    B:
    000000

    C:
    000000

    由于 Dominant 可以覆盖 Recessive:

    实际总线:

    000000000000

    因此:

    总线上的 Error Flag 是多个节点 Error Flag 的叠加结果。

    规范明确给出了:

    6~12 个连续 Dominant

    的范围。

    所以在 CAN 分析仪上看到:

    Error Flag = 8 bit

    或者:

    Error Flag = 10 bit

    并不意味着 CAN 协议出错。

    很可能只是:

    多个节点的 Error Flag 在时间上发生了重叠。


    十四、Passive Error Flag —— 隐性错误标志

    当一个节点进入:

    Error-Passive

    状态以后,它不能再发送 Active Error Flag。

    它发送:

    6 个 Recessive bit

    即:

    1 1 1 1 1 1

    这就是:

    Passive Error Flag。

    规范明确规定:

    • Active Error Flag = 6 个 Dominant
    • Passive Error Flag = 6 个 Recessive

    十五、为什么 Error-Passive 要改成隐性错误标志?

    这里体现了 CAN 很重要的“故障隔离”思想。

    假设某个节点已经频繁出错。

    如果它仍然可以无限制地发送:

    000000

    那么一个有问题的节点就可能不断破坏整个网络。

    所以 CAN 做了一件很聪明的事情:

    正常节点:

    Error-Active
    ↓
    可以强制发送 Dominant
    ↓
    可以立即破坏错误帧

    经常出错的节点:

    Error-Passive
    ↓
    不能再强制 Dominant
    ↓
    只能发送 Recessive Error Flag

    这样它仍然能够参与通信,但已经失去了“强制全网停止当前帧”的能力。

    这就是:

    Fault Confinement —— 故障隔离。


    十六、Error Delimiter —— 错误定界符

    Error Flag 后面紧跟:

    8 个 Recessive bit

    称为:

    Error Delimiter。

    因此典型结构可以理解成:

    Error Flag
    ↓
    6~12 个 Dominant
    ↓
    Error Delimiter
    ↓
    8 个 Recessive

    规范规定 Error Delimiter 为 8 个 Recessive bit。发送 Error Flag 后,各节点发送 Recessive 并监视总线,检测到 Recessive 后再发送其余的 Recessive bit,以完成 8-bit Error Delimiter。


    十七、从发送方角度看:发生错误以后到底发生什么?

    这是理解整个机制最重要的一部分。

    假设:

    节点 A 正在发送:

    A →→→ CAN Frame

    同时 A 自己也监视总线。


    情况一:A 发现 Bit Error

    例如:

    A发送:

    1

    总线:

    0

    并且此时不是仲裁允许的情况。

    那么:

    A
    ↓
    检测 Bit Error
    ↓
    下一 bit 开始 Error Flag
    ↓
    A发送 Active Error Flag
    ↓
    当前帧被破坏

    如果 A 是 Error-Active:

    Active Error Flag:

    000000

    其他节点看到之后,也会检测到错误。


    十八、如果是接收方先发现错误呢?

    假设:

    A:发送数据

    B:接收
    C:接收
    D:接收

    B 在 CRC 校验时发现:

    CRC错误

    那么 B:

    B
    ↓
    发现 CRC Error
    ↓
    当前帧不能接受
    ↓
    发送 Error Frame

    对于 Classical CAN 的 CRC Error,规范规定接收节点在 ACK Delimiter 之后发送 Error Frame。

    于是:

    A:正在发送

    B:发现 CRC Error
    ↓
    Error Flag
    ↓
    A、C、D 看到错误
    ↓
    当前帧被终止


    十九、所以 CAN 中存在两条完全不同的错误发现路径

    可以把它们总结成:

    CAN Frame
    │
    ┌─────────┴─────────┐
    │ │
    发送方 接收方
    │ │
    自己监听总线 检查收到的帧
    │ │
    Bit Error / ACK Stuff / CRC /
    等错误 Form 等错误
    │ │
    └─────────┬─────────┘
    ↓
    Error Flag
    ↓
    当前帧作废
    ↓
    自动重传

    这就是 CAN 错误处理的主线。


    二十、为什么“错误帧”不会被再次当成普通数据帧?

    因为 Error Flag 本身故意采用一种:

    违反正常 CAN 帧规则的特殊形式。

    Active Error Flag 的连续 6 个 Dominant 会违反 Bit Stuffing 规则或者固定字段格式。

    因此其他节点看到它以后,也会进入错误处理。

    所以 Error Frame 本质上不是:

    “一条特殊的数据消息”。

    而是:

    一种用于破坏当前通信、迫使所有节点放弃当前帧的协议控制机制。


    二十一、当前帧被破坏以后怎么办?

    CAN 并不是简单地:

    出错
    ↓
    丢弃
    ↓
    结束

    而是:

    检测错误
    ↓
    Error Flag
    ↓
    Error Delimiter
    ↓
    当前帧作废
    ↓
    重新参与总线仲裁
    ↓
    再次发送

    ISO 11898-1 明确规定:

    • 丢失仲裁的帧可以自动重传;
    • 没有获得 ACK 的帧可以自动重传;
    • 由于错误而被破坏的帧可以自动重传。

    二十二、一个非常重要的区别:Arbitration Lost 不属于 Error

    例如:

    A ID = 100
    B ID = 200

    A、B 同时发送。

    在仲裁过程中:

    A:Recessive
    B:Dominant

    Bus:Dominant

    A 发现自己输了。

    这不是:

    Error Frame

    也不是:

    TEC 增加

    而是:

    正常的 CAN 仲裁过程。

    A 退出,B 继续发送。

    所以:

    Lost Arbitration
    ≠
    Error

    这是 CAN 初学者必须牢牢记住的一点。


    二十三、TEC 和 REC 到底是什么?

    CAN 为每一个节点维护两个错误计数器:

    TEC

    Transmit Error Counter

    发送错误计数器。

    主要反映:

    这个节点作为发送者时发生错误的情况。


    REC

    Receive Error Counter

    接收错误计数器。

    主要反映:

    这个节点作为接收者时发现错误的情况。

    ISO 11898-1 要求所有节点具有发送错误计数器和接收错误计数器。规范指出,TEC 记录发送过程中的错误,REC 记录接收过程中的错误。


    二十四、为什么需要两个计数器?

    因为:

    “总线上有错误”并不等于“这个节点有问题”。

    例如:

    A →→→ B

    如果 A 的发送器坏了:

    A:
    发送错误很多

    那么 A 应该主要表现为:

    TEC ↑↑↑

    而 B 可能只是:

    REC ↑

    反过来,如果:

    总线受到外部干扰

    所有节点都可能发现错误。

    这时候不能简单认为:

    “发现错误的所有节点都是坏的。”

    因此 CAN 通过 TEC 和 REC 分别记录发送侧和接收侧的错误行为。


    二十五、TEC/REC 并不是“每出现一次 Error Frame 就简单 +1”

    这是另一个非常容易产生错误理解的地方。

    规范明确规定:

    错误计数规则非常具体,而且一次帧传输过程中可能同时适用多个规则。

    例如:

    接收节点检测到错误

    通常:

    REC += 1

    但有特殊情况。


    接收节点在发送 Error Flag 后检测到第一个 Dominant

    REC += 8


    发送节点发送 Error Flag

    通常:

    TEC += 8

    但是规范规定了两个特殊例外,在这两个例外情况下 TEC 不增加:

  • Error-Passive 发送节点由于没有检测到 ACK 而产生 ACK Error,同时发送 Passive Error Flag 时也没有检测到 Dominant;
  • 仲裁期间由于 Stuff Error 产生 Error Flag,而相关的 Stuff Bit 本应为 Recessive、实际也发送 Recessive,却监测到 Dominant。

  • 二十六、为什么错误时有时是 +1,有时是 +8?

    这是 CAN Fault Confinement 机制的关键。

    可以粗略理解:

    普通接收错误:

    REC +1

    严重/特殊错误响应:

    REC +8

    发送节点主动产生 Error Flag:

    TEC +8

    CAN 通过这种不同权重,使计数器能够反映:

    一个节点长期参与通信时,到底有多频繁地出现异常。

    规范对这种设计的总体解释是:

    正确发送/接收时计数器下降;出现错误时计数器增加,而且错误导致的增加速度高于正常通信造成的下降速度。


    二十七、成功以后 TEC/REC 会下降

    CAN 并不是:

    犯一次错误
    +
    永久记一笔

    而是:

    允许暂时性故障自动恢复。

    成功发送一帧:

    TEC -= 1

    最低不会低于 0。

    规范规定,成功发送的定义包括:

    • 得到 ACK;
    • 一直到 EOF 完成之前没有检测到错误。

    成功接收一帧:

    REC -= 1

    但是 REC 的下降有特殊规则:

    REC = 0
    ↓
    仍然保持 0

    1 ≤ REC ≤ 127
    ↓
    REC -= 1

    REC > 127
    ↓
    成功接收后
    设置到 119~127 范围


    二十八、因此 TEC/REC 更像“历史健康度”

    不要把 TEC/REC 理解成:

    “当前这一次错误的数量。”

    更准确地说:

    TEC/REC 是 CAN 节点近期错误行为的一种动态历史指标。

    如果一个节点:

    偶尔错误
    ↓
    之后长期正常
    ↓
    计数逐渐下降

    那么 CAN 会认为:

    可能只是临时干扰。

    如果一个节点:

    持续出错
    ↓
    错误增加速度 > 正常通信恢复速度
    ↓
    计数越来越高

    CAN 就逐渐降低这个节点的“破坏能力”。

    这就是:

    Fault Confinement。


    二十九、CAN 的三个错误状态

    根据错误计数器,CAN 节点存在三个状态:

    ┌──────────────┐
    │ Error-Active │
    └──────────────┘
    ↓
    ┌──────────────┐
    │ Error-Passive│
    └──────────────┘
    ↓
    ┌──────────────┐
    │ Bus-Off │
    └──────────────┘

    规范明确规定节点的三种状态就是:

    • Error-Active
    • Error-Passive
    • Bus-Off

    三十、Error-Active 是什么?

    这是正常状态。

    Error-Active 节点:

    • 正常参与 CAN 通信;
    • 可以发送数据;
    • 可以接收数据;
    • 发现错误时可以发送 Active Error Flag。

    也就是:

    正常通信
    +
    正常纠错能力

    Active Error Flag:

    000000


    三十一、什么时候进入 Error-Passive?

    规范规定:

    如果 TEC 或 REC 超过 127,则节点进入 Error-Passive。

    也就是:

    TEC > 127
    OR
    REC > 127
    ↓
    Error-Passive

    注意这里是:

    大于 127

    而不是“达到 127”。

    因此工程上常说:

    Error Passive threshold = 128

    是为了方便理解,但规范本身的表达是:

    counter exceeds 127。


    三十二、进入 Error-Passive 时有什么特别的地方?

    这里有一个很容易忽略的细节。

    规范规定:

    导致节点进入 Error-Passive 的那个错误条件,会使节点发送 Active Error Flag。

    也就是说:

    原本:

    Error-Active

    发生一次错误
    ↓
    计数器超过 127
    ↓
    状态变成 Error-Passive

    但:

    这个导致状态变化的错误本身仍然会触发 Active Error Flag。

    所以不能简单理解成:

    TEC=128
    ↓
    立刻以后只能发 Passive Error Flag

    状态转换发生在具体错误处理流程中,需要结合该次错误的处理。


    三十三、Error-Passive 以后有什么变化?

    最大的变化就是:

    不能再发送 Active Error Flag

    而是:

    Passive Error Flag

    111111

    也就是:

    6 个 Recessive。

    另外:

    如果 Error-Passive 节点刚刚作为发送者发送完一帧,它还必须增加 Suspend Transmission 时间。

    规范规定:

    Intermission
    +
    8 bit times suspend transmission

    之后才能开始新的发送。

    这进一步降低了一个错误节点对总线的影响。


    三十四、Error-Passive 会不会永远恢复不了?

    不会。

    如果错误只是暂时的,TEC/REC 会随着成功通信逐渐下降。

    规范规定:

    Error-Passive 节点只有在 TEC 和 REC 都 ≤127 时,才能重新进入 Error-Active。

    所以:

    TEC ≤ 127
    AND
    REC ≤ 127
    ↓
    Error-Active

    注意:

    必须两个计数器都满足条件。

    不是:

    TEC ≤127

    就恢复。

    也不是:

    REC ≤127

    就恢复。


    三十五、Bus-Off 是什么?

    如果:

    TEC > 255

    CAN 节点进入:

    Bus-Off

    这是比 Error-Passive 更严重的状态。

    规范规定,TEC 超过 255 后,Fault Confinement Supervisor 请求物理层把节点切换到 Bus-Off。


    三十六、Bus-Off 和 Error-Passive 的根本区别

    可以这样理解:

    Error-Active

    我正常工作
    发现错误
    → 我可以主动破坏错误帧

    Error-Passive

    我最近经常出错
    ↓
    我还可以通信
    ↓
    但我不能主动破坏总线

    Bus-Off

    我已经严重到不能继续参与总线
    ↓
    彻底退出

    规范对 Bus-Off 的定义非常严格:

    Bus-Off 节点对总线没有影响。

    它:

    • 不发送帧;
    • 不发送 ACK;
    • 不产生 Dominant bit;
    • 逻辑上从总线断开。

    三十七、为什么 Bus-Off 要这么狠?

    假设一个 ECU 的 CAN 收发器或者控制器出了严重问题:

    一直发送错误
    一直发送 Error Flag
    一直破坏别人数据

    如果 CAN 没有 Bus-Off:

    坏节点
    ↓
    持续制造错误
    ↓
    所有节点不断重传
    ↓
    整个 CAN 网络瘫痪

    CAN 的设计选择是:

    错误少:
    正常参与

    错误多:
    降低错误影响

    错误非常多:
    直接退出总线

    这就是 Fault Confinement 的核心。

    ISO 11898-1 明确把 Fault Confinement 的目标定义为:

    即使存在故障节点,也尽量保持数据传输网络的高可用性,同时区分临时错误和永久故障,并定位、关闭故障节点。


    三十八、Bus-Off 后是不是自动马上恢复?

    这里一定要注意:

    不是简单的“TEC 降到 255 以下就自动恢复”。

    规范规定:

    Bus-Off 节点在收到 Restart Request 后进入 Bus Integration 状态。

    然后它必须监视总线上的:

    128 次 Idle Condition

    之后才可以重新成为 Error-Active,并且:

    TEC = 0
    REC = 0


    三十九、什么叫一次 Idle Condition?

    ISO 11898-1 将 Idle Condition 定义为:

    检测到连续 11 个 Recessive bits。

    也就是说:

    11111111111

    就是一次 Idle Condition。

    所以 Bus-Off Recovery 的核心不是:

    等一段固定时间

    而是:

    等待并观察总线
    ↓
    检测 11 个连续 Recessive
    ↓
    记为一次 Idle Condition
    ↓
    继续观察
    ↓
    累计 128 次
    ↓
    恢复


    四十、因此 Bus-Off Recovery 实际上是一个“观察期”

    可以画成:

    BUS-OFF
    │
    │ Restart Request
    ↓
    Bus Integration
    │
    ├── 11 Recessive → Idle #1
    │
    ├── 11 Recessive → Idle #2
    │
    ├── 11 Recessive → Idle #3
    │
    │ …
    │
    ├── 11 Recessive → Idle #128
    │
    ↓
    TEC = 0
    REC = 0
    ↓
    ERROR-ACTIVE

    如果在 Integration 过程中总线再次出现 Dominant:

    当前连续 Recessive 计数
    ↓
    重新开始

    规范规定,Bus Integration 状态中的 bit counter 在检测到 Dominant 时复位,连续检测到 11 个 Recessive 才形成 Idle Condition。


    四十一、把整个错误处理过程串起来

    现在把前面所有机制连起来。

    假设:

    A = Transmitter
    B/C/D = Receivers

    A 正在发送:

    CAN Data Frame


    第一步:A、B、C、D 都在检查

    A:
    监视自己发送的 bit

    B:
    检查帧格式 / Stuff / CRC 等

    C:
    检查帧格式 / Stuff / CRC 等

    D:
    检查帧格式 / Stuff / CRC 等


    第二步:某一个节点发现错误

    可能是:

    A → Bit Error / ACK Error

    B → Stuff Error / CRC Error / Form Error

    C → Stuff Error / CRC Error / Form Error


    第三步:发现错误的节点产生 Error Flag

    Error-Active:

    000000

    Error-Passive:

    111111


    第四步:Error Flag 传播到整个总线

    Active Error Flag 的 Dominant bits 会破坏正常帧。

    其他节点也可能检测到错误。

    于是:

    A ── Error Flag
    B ──── Error Flag
    C ────── Error Flag

    最终总线可能看到:

    0000000000…

    实际连续 Dominant 长度可能为:

    6~12 bit


    四十二、第五步:Error Delimiter

    Error Flag 结束后:

    11111111

    即:

    8 个 Recessive。

    进入错误定界阶段。


    四十三、第六步:原来的帧被放弃

    这个时候:

    原来的 CAN Frame
    ↓
    无效
    ↓
    不会交给上层作为有效数据

    然后按照 Recovery Management:

    重新发送

    规范规定,被错误破坏、没有 ACK 或丢失仲裁的帧可以自动重新参与发送。


    四十四、第七步:错误计数器发生变化

    例如:

    发送节点产生 Error Flag

    通常:

    TEC += 8

    接收节点发现错误

    通常:

    REC += 1

    接收节点在 Error Flag 后检测到第一个 Dominant

    REC += 8

    成功发送

    TEC -= 1

    成功接收

    REC -= 1

    具体特殊情况仍必须按照 ISO 11898-1 的错误计数规则处理。


    四十五、最终形成三个状态

    正常
    │
    ▼
    ┌─────────────┐
    │ Error-Active│
    └─────────────┘
    │
    TEC >127
    或 REC >127
    │
    ▼
    ┌─────────────┐
    │Error-Passive│
    └─────────────┘
    │
    TEC >255
    │
    ▼
    ┌─────────────┐
    │ Bus-Off │
    └─────────────┘

    恢复方向:

    Error-Passive
    │
    TEC ≤127
    AND
    REC ≤127
    ↓
    Error-Active

    Bus-Off:

    Bus-Off
    │
    Restart Request
    ↓
    Integration
    │
    128 × Idle Condition
    ↓
    TEC=0, REC=0
    ↓
    Error-Active


    四十六、一个非常重要的工程误区:REC 高不一定说明这个 ECU 坏了

    这是实际维修和 CAN 分析中非常重要的一点。

    例如:

    总线物理层受到严重干扰

    可能导致:

    A:REC ↑
    B:REC ↑
    C:REC ↑
    D:REC ↑

    这并不意味着:

    A坏了
    B坏了
    C坏了
    D坏了

    而可能是:

    CANH/CANL
    终端电阻
    接插件
    电磁干扰
    时序问题
    收发器

    等总线层面的共同问题。

    因此:

    REC 是“节点观察到的接收错误历史”,不是 ECU 故障诊断结论。

    同样:

    TEC 高也不能仅凭这一点直接判断 ECU 一定硬件损坏。

    必须结合错误类型、错误出现位置、总线波形、其他节点状态等信息判断。


    四十七、再看一个非常典型的 ACK Error

    假设:

    A = 唯一在线节点

    A 发送:

    SOF
    ID
    …
    CRC
    ACK Slot
    EOF

    ACK Slot:

    A发送:Recessive
    其他节点:没有
    总线:Recessive

    A:

    没有检测到 Dominant
    ↓
    ACK Error
    ↓
    Error Flag
    ↓
    TEC 按规则增加
    ↓
    自动重传

    于是可能出现:

    A发送
    ↓
    ACK Error
    ↓
    重传
    ↓
    ACK Error
    ↓
    重传
    ↓
    …

    所以:

    CAN 总线上一个节点独自工作时,它的 CAN 控制器出现 ACK Error 是正常的协议结果,并不能直接说明发送器坏了。

    规范的 Network Start-up 部分明确考虑了只有一个节点在线而没有 ACK 的情况。


    四十八、Error Flag 和 Overload Flag 不要混淆

    CAN 还有:

    Overload Frame

    即:

    Overload Frame / OF

    它不是 Error Frame。

    二者虽然形式非常相似:

    Overload Flag
    = 6 Dominant

    Error Active Flag
    = 6 Dominant

    但含义不同。

    Error Frame:

    表示:

    检测到了错误。

    Overload Frame:

    表示:

    需要额外延迟下一帧。

    规范规定 Overload Frame 用于提供额外延迟;它可以由 LLC 内部条件请求,也可以由 MAC 在特定情况下产生 Reactive Overload。

    所以:

    Error Frame
    ≠
    Overload Frame

    虽然在总线上都可能看到:

    000000


    四十九、为什么 CAN 的错误恢复这么快?

    规范给出了一个非常有意义的指标:

    如果后续不再发生错误,从检测错误到可能开始下一帧:

    通常约 17~23 个 nominal bit times

    对于 Error-Passive 节点:

    最多约 31 个 nominal bit times

    这说明 CAN 的错误处理不是:

    发生错误
    ↓
    等待很久
    ↓
    重新初始化

    而是:

    发现错误
    ↓
    立即破坏错误帧
    ↓
    Error Delimiter
    ↓
    重新仲裁
    ↓
    重新发送

    整个过程非常短。


    五十、CAN 错误机制真正厉害的地方在哪里?

    如果只看:

    Bit Error
    CRC
    Error Flag
    TEC
    REC
    Bus-Off

    很容易认为这些只是一些零散规则。

    实际上它们是一套完整的系统。

    可以把 CAN 的错误处理分成五层:

    第一层
    错误检测
    ↓
    “我发现这里不对”

    第二层
    错误信号
    ↓
    “这帧不能继续了”

    第三层
    错误恢复
    ↓
    “这帧重新发送”

    第四层
    错误统计
    ↓
    “这个节点最近到底出了多少问题?”

    第五层
    故障隔离
    ↓
    “如果你一直出问题,就限制你,
    甚至把你踢出总线。”


    五十一、这就是 CAN 的工程哲学

    ISO 11898-1 对 Fault Confinement 的描述实际上体现了 CAN 最核心的设计思想:

    区分临时错误和永久故障。

    CAN 不会因为一次错误就把一个节点踢出去。

    而是:

    偶发错误
    ↓
    计数
    ↓
    恢复正常
    ↓
    计数下降

    只有:

    持续错误
    ↓
    错误计数持续增加
    ↓
    Error-Passive
    ↓
    仍然持续严重出错
    ↓
    Bus-Off

    因此 CAN 的错误处理实际上是:

    “容忍短暂错误,但限制持续制造错误的节点。”


    五十二、CAN 的另一个核心哲学:不能让一个坏节点拖垮整个网络

    可以把它想象成一个团队:

    正常节点:
    “我发现问题,我立即叫停这次错误通信。”

    问题节点开始变坏:
    “我仍然可以通信,但不能再强制打断别人。”

    问题继续恶化:
    “你暂时离开网络。”

    问题解决以后:
    “观察一段时间,确认总线正常,再回来。”

    这就是:

    Error-Active
    ↓
    Error-Passive
    ↓
    Bus-Off

    以及:

    Bus-Off
    ↓
    Bus Integration
    ↓
    128 Idle Conditions
    ↓
    重新加入

    它不是简单的“错误计数器”,而是一套:

    分级容错 + 故障隔离 + 自动恢复机制。


    五十三、从发送方和接收方分别总结

    发送方

    发送节点主要关注:

    我发送了什么?
    ↓
    总线实际上是什么?
    ↓
    有没有 ACK?
    ↓
    有没有发生发送过程中的错误?

    可能发现:

    • Bit Error
    • ACK Error
    • 以及发送过程中相应的协议错误

    如果发现需要发送 Error Flag:

    Error-Active
    → Active Error Flag

    Error-Passive
    → Passive Error Flag

    错误导致的计数主要影响:

    TEC

    成功发送后:

    TEC -= 1

    持续发送错误:

    TEC ↑
    ↓
    >127
    ↓
    Error-Passive
    ↓
    >255
    ↓
    Bus-Off


    五十四、接收方

    接收节点主要关注:

    这个帧格式对不对?
    Stuff 对不对?
    CRC 对不对?
    固定字段对不对?

    可能发现:

    • Stuff Error
    • CRC Error
    • Form Error
    • Bit Error
    • 以及其他协议规定的接收错误

    发现错误:

    发送 Error Flag

    错误主要影响:

    REC

    成功接收:

    REC 下降

    持续检测错误:

    REC ↑
    ↓
    >127
    ↓
    Error-Passive

    如果错误停止,REC 可以逐步下降,最终重新进入 Error-Active。


    五十五、把整个 CAN 错误机制浓缩成一张图

    CAN FRAME
    │
    ┌──────────────┴──────────────┐
    │ │
    发送方 接收方
    │ │
    监视总线 检查收到的帧
    │ │
    Bit Error / ACK Stuff / CRC /
    等错误 Form / Bit 等
    │ │
    └──────────────┬──────────────┘
    ↓
    Error detected
    │
    ↓
    Error Flag
    │
    ┌──────────┴──────────┐
    │ │
    Error-Active Error-Passive
    │ │
    6 Dominant bits 6 Recessive bits
    │ │
    └──────────┬──────────┘
    ↓
    Error Delimiter
    8 Recessive
    │
    ↓
    当前帧作废
    │
    ↓
    Automatic Retry
    │
    ┌───────────┴───────────┐
    │ │
    错误减少 错误持续
    │ │
    TEC/REC下降 TEC/REC上升
    │ │
    ↓ >127
    Error-Active │
    Error-Passive
    │
    TEC >255
    │
    ↓
    Bus-Off
    │
    Restart Request
    │
    ↓
    Bus Integration
    │
    128 Idle Conditions
    │
    ↓
    TEC=0 / REC=0
    │
    ↓
    Error-Active


    五十六、最后用一句话理解 TEC、REC 和 Bus-Off

    可以把它们记成:

    REC

    “我作为接收者,最近看到多少错误?”

    TEC

    “我作为发送者,最近发生多少错误?”

    Error-Active

    “我正常参与通信,也有权主动发出显性错误标志。”

    Error-Passive

    “我最近错误太多了,我还能通信,但不能再用显性错误标志强制打断总线。”

    Bus-Off

    “我已经严重到不能继续影响总线,先退出。”


    五十七、最终理解 CAN Error Frame,真正应该抓住的不是几个数字

    很多资料最后都会变成:

    TEC >127
    TEC >255
    REC >127
    6个0
    6个1
    8个1
    128次

    这些数字当然重要。

    但如果只记数字,很容易把 CAN 错误机制理解成死记硬背。

    真正应该理解的是下面这条逻辑链:

    发现错误 → 立即标记错误 → 破坏当前帧 → 所有节点放弃当前帧 → 自动重传 → 记录错误历史 → 错误持续则降低节点权限 → 再持续则 Bus-Off → 观察总线恢复后重新加入。

    这才是 CAN Error Handling 的完整逻辑。

    而它背后的工程哲学只有一句话:

    CAN 不追求“永远没有错误”,而是追求“即使出现错误,网络仍然能够快速发现、快速恢复,并把持续制造错误的节点隔离出去”。

    这也是 ISO 11898-1 中 Fault Confinement 机制最核心的思想。


    规范依据

    本文主要依据你提供的 ISO 11898-1:2015:

    • 6.8 Error detection
    • 6.9 Error signalling and recovery time
    • 6.10 ACK
    • 6.11 Automatic retransmission
    • 6.12 Fault confinement
    • 6.13 Error-active
    • 6.14 Error-passive
    • 6.15 Bus-off
    • 10.11 Error detection
    • 10.12 Error signalling
    • 12.1.1 Fault confinement objectives
    • 12.1.2 Fault confinement strategies
    • 12.1.4 Rules of fault confinement
    • 12.1.4.2 Error counting
    • 12.1.4.3 Transition between Error-Active and Error-Passive
    • 12.1.4.4 Bus-Off management

    其中规范明确指出 CAN 通过错误检测、错误信号、自动重传以及故障隔离,使网络能够区分短暂干扰与持续故障,并将持续产生错误的节点最终从总线隔离。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » CAN 总线错误处理机制详解
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!