4、CAN远程帧与错误帧:远程帧的作用、错误帧的产生机制、错误帧的格式

各位工程师朋友,咱们今天聊聊CAN总线里两个比较「特殊」的帧——远程帧和错误帧。

说实话,远程帧在日常开发中用的频率不算高,但一旦用对了,能省不少事。而错误帧呢?嗯,这玩意儿你肯定不想在总线上看到它,但你必须懂它。我当年调试第一块CAN板子时,就被错误帧折腾得够呛。

4.1 远程帧的作用

远程帧,说白了就是「请求数据」的帧。

你想想看,正常情况下,一个节点想发数据,它自己主动发数据帧就行了。但有时候,某个节点需要另一个节点的数据,怎么办?它就可以发一个远程帧过去,告诉对方:「嘿,把你那个ID的数据给我发过来。」

远程帧和数据帧的区别在哪里?

我习惯这样记:数据帧是「我有数据要给你」,远程帧是「你有没有数据?给我一份」。

具体区别看这张表:

对比项 数据帧 远程帧
RTR位 显性(0) 隐性(1)
数据场 有数据 无数据
目的 发送数据 请求数据
DLC 实际数据长度 请求的数据长度

远程帧的格式其实和数据帧几乎一样,唯一的区别就是RTR位。数据帧的RTR是显性0,远程帧是隐性1。就这么一个位,决定了帧的性质。

关键点:远程帧没有数据场!它的DLC字段表示的是「我想要多少字节的数据」,而不是「我发了多少字节」。

我在项目中遇到过这样一个场景:一个温度采集节点,平时处于低功耗模式。主控节点每隔一段时间发一个远程帧过去,温度节点收到后立刻采集温度并回复数据帧。这样既省电,又避免了温度节点一直发空数据占总线。

4.2 错误帧的产生机制

错误帧,是CAN总线上的「警报器」。

一旦某个节点检测到总线上的信号有问题,它就会立刻拉低总线,通知所有节点:「出错了,大家注意!」

为什么会出错?我总结了几种常见情况:

  • 位错误:节点发送了一个显性位,但总线上读到的是隐性位。或者反过来。说白了就是「我说的话和听到的不一样」。
  • 填充错误:连续出现了6个相同电平的位。CAN协议规定,连续5个相同位后必须插入一个相反位。如果没插,就是填充错误。
  • CRC错误:接收节点算出来的CRC和发送节点的不一致。数据在传输过程中被干扰了。
  • 格式错误:帧的格式不对,比如EOF应该是隐性位,结果读到了显性位。
  • 应答错误:发送节点没收到应答位(ACK)。也就是说,总线上没有一个节点确认收到了这个帧。

我记得有一次调试,总线上老是出现错误帧。查了半天,发现是一个节点的终端电阻没焊好,信号反射导致位错误。嗯,硬件上的小问题,往往是最难查的。

避坑指南:我曾经遇到过一个案例,某个节点频繁发送错误帧,导致整个总线瘫痪。最后发现是那个节点的晶振偏差太大,位时序完全乱了。所以,选晶振时别图便宜,精度一定要够。

4.3 错误帧的格式

错误帧的结构很简单,就两部分:

  1. 错误标志:6个连续的显性位
  2. 错误界定符:8个连续的隐性位

你想想看,6个显性位,这违反了位填充规则(连续5个相同位就要插反位)。所以,其他节点一看到这6个显性位,就知道出错了。

这里有个细节:错误标志有两种情况——

  • 主动错误标志:6个显性位。由处于「主动错误状态」的节点发出。
  • 被动错误标志:6个隐性位。由处于「被动错误状态」的节点发出。

什么意思呢?每个节点都有一个错误计数器。错误少的时候是「主动错误状态」,可以正常发错误帧。错误多了就变成「被动错误状态」,只能发隐性位的错误标志,不敢再拉低总线了。再严重下去,就是「总线关闭状态」,彻底闭嘴。

错误界定符的8个隐性位,是为了让总线恢复空闲状态。错误帧发完后,总线必须有一段安静时间,大家才能重新开始通信。

个人经验:我建议你在调试时,用示波器抓一下错误帧的波形。看到那6个显性位紧跟着8个隐性位,你就知道错误帧长什么样了。看波形比看文字直观得多。

最后说一句,错误帧不是用来「修复」错误的,它只是用来「通知」错误的。真正处理错误,要靠上层协议或者重发机制。CAN控制器会自动重发被错误帧打断的数据帧,这一点倒是挺省心的。

好了,远程帧和错误帧就聊到这儿。下一章咱们讲讲CAN的位时序和同步机制,那个才是真正考验功底的地方。