——从 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 规定了多种错误检测方法。
主要包括:
规范明确规定了五类基本错误:
| 位错误 | 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 有两种
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 不增加:
二十六、为什么错误时有时是 +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 通过错误检测、错误信号、自动重传以及故障隔离,使网络能够区分短暂干扰与持续故障,并将持续产生错误的节点最终从总线隔离。
网硕互联帮助中心




评论前必须登录!
注册