2、CAN协议基础:CAN数据帧结构、CAN远程帧、CAN错误帧、CAN过载帧、帧间隔

好,咱们进入正题。CAN协议里最核心的,就是这几种帧。说白了,CAN总线上的所有通信,都是靠这些帧来完成的。我刚开始接触CAN的时候,也被这些帧的名字搞得有点晕。但别怕,咱们一个一个拆开看。

2.1 CAN数据帧:最常用的“快递包裹”

数据帧,就是用来发送数据的。你可以把它想象成一个快递包裹。这个包裹有固定的格式,谁寄的、寄给谁、里面装了什么,都得写清楚。

数据帧有两种格式:标准帧扩展帧。区别就在于ID的长度。标准帧ID是11位,扩展帧ID是29位。我个人习惯,如果项目里节点不多,用标准帧就够了,简单高效。

一个完整的数据帧,由以下几个部分组成:

  • 帧起始(SOF):一个显性位(0)。告诉总线上的所有节点:“我要开始发数据了!”
  • 仲裁场:包含ID和RTR位。ID决定了消息的优先级。ID越小,优先级越高。RTR位用来区分是数据帧还是远程帧。
  • 控制场:包含IDE位和DLC。IDE位用来区分是标准帧还是扩展帧。DLC表示数据场有多少个字节(0-8)。
  • 数据场:0到8个字节的数据。这就是你要发送的真正内容。
  • CRC场:循环冗余校验。用来检查数据在传输过程中有没有出错。
  • ACK场:应答场。接收节点如果正确收到了数据,就会在这里回一个显性位,告诉发送方:“我收到了!”
  • 帧结束(EOF):7个隐性位(1)。表示这个帧结束了。

重点:仲裁场是CAN总线实现“无损位仲裁”的关键。多个节点同时发送时,ID最小的那个会赢得仲裁,继续发送。其他节点自动转为接收。这个机制非常巧妙,我当年第一次理解时,觉得设计者真是个天才。

我的经验:在设计系统时,一定要把紧急消息的ID设小一点。比如刹车指令的ID设为0x001,车窗指令设为0x100。这样刹车指令永远优先。我曾经在一个项目中,把两个关键消息的ID设反了,结果调试时发现优先级总是不对,查了半天才找到原因。

2.2 CAN远程帧:请求数据的“挂号信”

远程帧,说白了就是“请求数据”。一个节点如果想从另一个节点获取数据,就可以发一个远程帧。远程帧的结构和数据帧几乎一样,唯一的区别是RTR位是隐性位(1)。

远程帧没有数据场。它的DLC字段表示它希望接收多少字节的数据。比如,节点A发一个远程帧,ID=0x100,DLC=4。那么节点B收到后,就知道节点A想要ID为0x100的4个字节数据。节点B就会发一个数据帧,ID=0x100,数据场里放4个字节。

注意:远程帧的ID和数据帧的ID是共享的。也就是说,你不能同时用同一个ID既发数据帧又发远程帧。否则会冲突。我曾经见过一个新手,把远程帧和数据帧的ID设成一样,结果总线上一片混乱。

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

错误帧,是CAN总线自我保护的机制。当任何一个节点检测到错误时,就会发送错误帧。错误帧由两部分组成:错误标志错误界定符

  • 错误标志:6个连续的显性位(0)。这会破坏当前正在传输的帧,让所有节点都知道出错了。
  • 错误界定符:8个连续的隐性位(1)。用来结束错误帧。

CAN协议定义了五种错误类型:

错误类型 说明
位错误 发送节点发送的位和总线上监测到的位不一致。
填充错误 连续出现了6个相同电平的位(违反位填充规则)。
CRC错误 接收节点计算的CRC和发送节点的CRC不一致。
形式错误 帧的固定格式部分出现错误(比如EOF不是7个隐性位)。
应答错误 发送节点没有收到ACK应答。

避坑指南:我曾经在一个项目中,发现总线偶尔会莫名其妙地报错。查了很久,最后发现是一个节点的晶振频率偏差太大,导致位时序不对。嗯,这里要注意,CAN总线的位时序对时钟精度要求很高。如果时钟不准,很容易出现位错误。

2.4 CAN过载帧:总线的“稍等一下”

过载帧,用来告诉发送节点:“我忙不过来了,你慢点发。” 它和错误帧的结构很像,也是由过载标志过载界定符组成。

  • 过载标志:6个连续的显性位(0)。
  • 过载界定符:8个连续的隐性位(1)。

过载帧通常在两种情况下产生:

  1. 接收节点内部条件不满足,无法处理下一个数据。
  2. 在帧间隔期间,检测到显性位(这被视为一个过载条件)。

我的建议:过载帧在实际项目中用得不多。因为大多数MCU的CAN控制器都有硬件FIFO,可以缓存多个消息。除非你的系统负载极高,否则很少需要主动发送过载帧。但了解它还是有必要的,万一哪天遇到了,不至于抓瞎。

2.5 帧间隔:总线的“休息时间”

帧间隔,就是两个帧之间的空闲时间。它用来让总线上的节点有时间准备接收下一个帧。帧间隔由间歇场总线空闲组成。

  • 间歇场:3个隐性位(1)。
  • 总线空闲:任意长度的隐性位(1)。只要总线是空闲的,节点就可以开始发送。

这里有个细节:对于被动错误节点,帧间隔还会多一个挂起传输场(8个隐性位)。这是为了让主动错误节点有机会先发送。

总结一下:数据帧是主力,远程帧是辅助,错误帧是保安,过载帧是协调员,帧间隔是休息时间。这五种帧共同构成了CAN总线的通信基础。你想想看,一个总线协议能把这些都考虑进去,是不是很厉害?

好了,这一章的内容就到这里。下一章我们会深入CAN的位时序和同步机制,那才是真正考验功底的地方。做好准备!