3. CAN远程帧与错误帧:不只是收发数据那么简单

各位工程师朋友,咱们继续聊CAN总线。前两章我们把数据帧和遥控帧的基本概念过了一遍,今天要讲的是两个容易被忽视、但实际项目中坑最多的东西——远程帧和错误帧。

说实话,我刚入行那会儿,觉得远程帧就是个“请求数据”的小工具,错误帧嘛,出错了才用得上。直到有一次在台架上跑测试,总线莫名其妙挂掉,折腾了两天才发现是错误帧风暴导致的。嗯,从那以后我再也不敢小看这两个家伙了。

3.1 远程帧:它到底在干什么?

远程帧,也叫RTR帧(Remote Transmission Request)。说白了,就是一个节点告诉另一个节点:“嘿,把你手上那个ID的数据发给我看看。”

你可能会问:为什么不直接发数据帧?非要搞个远程帧来“请求”?

我个人的理解是:远程帧的核心价值在于“按需索取”。比如一个传感器节点平时不主动发数据,只有仪表盘需要时才请求一次。这样能省不少总线带宽。

3.1.1 远程帧的结构

远程帧的结构和数据帧非常像,但有两个关键区别:

  • RTR位:远程帧的RTR位为隐性(1),数据帧为显性(0)
  • 数据场:远程帧没有数据场,DLC(数据长度码)虽然存在,但实际不传输数据

来看一个标准格式的远程帧结构:

SOF | 11位ID | RTR(1) | IDE | r0 | 4位DLC | CRC | ACK | EOF
 1     11       1       1     1     4       15    2     7

注意看,RTR位是1(隐性),这就是远程帧的“身份证”。

关键点:远程帧的DLC虽然存在,但它只表示请求的数据长度,并不携带数据字节。所以远程帧的总长度比数据帧短很多。

3.1.2 远程帧的工作流程

我画了一张图,帮你理解远程帧的交互过程:

远程帧交互流程 节点A(请求方) 节点B(响应方) ① 发送远程帧(ID=0x123, RTR=1) ② 发送数据帧(ID=0x123, 8字节数据) 💡 注意: • 远程帧的ID必须与响应数据帧的ID相同 • 远程帧本身不携带数据,只携带DLC • 响应节点必须在收到远程帧后尽快回复数据帧

我的经验:在实际项目中,远程帧用得最多的是诊断服务和传感器数据请求。但要注意,如果多个节点同时请求同一个ID的远程帧,可能会引发总线冲突。我曾经在一个项目中遇到过,三个ECU同时请求同一个传感器的数据,结果总线上一片混乱。后来我们加了一个请求仲裁机制才解决。

3.2 错误帧:总线的“警报器”

错误帧是CAN总线自我保护的机制。当任何一个节点检测到总线上的错误时,就会发送错误帧来通知其他节点。

你想想看,如果总线上有节点在乱发数据,其他节点怎么办?总不能一直忍着吧。错误帧就是用来“喊停”的。

3.2.1 错误帧的结构

错误帧由两部分组成:

  • 错误标志:6个连续的显性位(主动错误)或6个连续的隐性位(被动错误)
  • 错误界定符:8个连续的隐性位

结构图如下:

错误标志(6位) | 错误界定符(8位)
  显性/隐性         隐性

这里有个细节:错误标志的6位会破坏当前正在传输的帧的填充位规则,从而让其他节点也检测到错误。

3.2.2 错误帧的触发条件

CAN总线定义了5种错误类型,任何一类都会触发错误帧:

错误类型 触发条件 检测节点
位错误 发送节点监控到总线电平与发送电平不一致 发送节点
填充错误 连续出现6个相同电平的位(违反位填充规则) 所有节点
CRC错误 接收节点计算的CRC与发送的CRC不匹配 接收节点
格式错误 帧格式中的固定位出现错误电平 所有节点
ACK错误 发送节点在ACK槽未检测到显性位 发送节点

避坑指南:我曾经在一个项目中遇到“幽灵错误”——总线偶尔出现错误帧,但用示波器抓波形又看不出问题。后来排查了三天,发现是一个节点的晶振精度不够,导致位时序偏差。所以,时钟精度是错误帧排查中容易被忽略的因素。

3.3 错误状态:主动、被动与总线关闭

CAN总线上的每个节点都有一个错误计数器,分为发送错误计数器(TEC)和接收错误计数器(REC)。根据计数器的值,节点会处于三种状态之一。

我习惯用“交通规则”来类比:

  • 主动错误:你是正常司机,看到违规可以大声喊停
  • 被动错误:你被扣了分,只能小声提醒
  • 总线关闭:你的驾照被吊销了,不能上路

3.3.1 三种状态详解

状态 条件 错误标志 行为
主动错误 TEC ≤ 127 且 REC ≤ 127 6个显性位 正常参与通信,检测到错误时主动发送错误帧
被动错误 TEC > 127 或 REC > 127 6个隐性位 只能发送被动错误帧,不能破坏其他节点的帧
总线关闭 TEC > 255 不发送 完全脱离总线,不参与任何通信

状态转换流程如下:

CAN节点错误状态转换图 主动错误 TEC≤127 且 REC≤127 被动错误 TEC>127 或 REC>127 总线关闭 TEC>255 错误累积 严重错误 128次总线空闲后恢复 错误计数器归零后恢复 💡 虚线表示恢复路径:总线关闭后需等待128个总线空闲信号才能回到主动错误

3.3.2 错误计数器的增减规则

很多初学者搞不清计数器怎么加减。我总结了一个简化版规则:

  • 发送成功:TEC减1(但TEC不会低于0)
  • 发送错误:TEC加8
  • 接收错误:REC加1
  • 被动错误节点发送成功:TEC减1(但不会低于127)

核心逻辑:错误计数器采用“重罚轻奖”策略。发送一次错误加8分,发送成功才减1分。这样设计是为了让频繁出错的节点快速进入被动状态,避免它持续破坏总线。

3.4 实战中的错误帧排查

在实际测试中,错误帧是最常见的“捣乱分子”。我分享几个排查思路:

  1. 用CAN工具抓错误帧统计:大部分CAN分析仪都能统计错误帧数量和类型
  2. 观察错误计数器:通过诊断服务读取节点的TEC和REC值
  3. 检查终端电阻:终端电阻异常会导致信号反射,引发位错误
  4. 排查时钟精度:位时序偏差是CRC错误的常见原因
  5. 检查接地:共模电压过高会导致隐性电平无法正常识别

我曾经踩过的坑:有一次测试中,总线偶尔出现错误帧,但频率不高。我们用CAN工具抓了半小时才抓到一次。后来发现是一个节点的CAN收发器供电滤波电容虚焊,导致电源纹波过大,偶尔触发位错误。所以,硬件可靠性也是错误帧排查的重要方向。

3.5 本章小结

远程帧和错误帧是CAN总线协议中容易被忽视、但实际影响巨大的部分。远程帧实现了“按需索取”的数据请求机制,而错误帧则是总线自我修复的核心手段。

理解错误状态的转换逻辑,掌握错误计数器的增减规则,能帮你快速定位总线故障。记住:总线关闭不是终点,而是节点自我保护的最后一道防线。