3、CAN总线详解:CAN 2.0与CAN FD协议差异,帧结构,仲裁机制,位时序配置

好,咱们今天来聊聊CAN总线。说实话,在飞控系统里,CAN总线就像飞机的神经血管。我这些年调试过的飞控板,十有八九都离不开它。你想想看,电机、舵机、传感器,这些关键节点全靠它串起来。要是CAN总线出问题,飞机基本就“断线”了。

这一节,我带你从底层把CAN总线扒清楚。咱们重点看四个东西:CAN 2.0和CAN FD到底差在哪、帧结构长什么样、仲裁机制怎么抢总线、还有那个让人头疼的位时序配置。

3.1 CAN 2.0 vs CAN FD:差的不只是速度

很多人以为CAN FD就是“快一点的CAN”。嗯,这话对了一半。CAN FD确实快,但它的核心改进,其实是数据量。

我最早接触CAN FD是在一个四轴飞行器项目上。当时用CAN 2.0,一帧只能发8个字节。你要传个姿态解算结果,还得拆成好几帧。后来换了CAN FD,一帧能干到64字节,舒服多了。

咱们看个对比表,一目了然:

特性 CAN 2.0 CAN FD
数据长度 最多8字节 最多64字节
最大速率 1 Mbps 数据段可达8 Mbps
帧格式 标准/扩展帧 兼容CAN 2.0,新增FDF标志
CRC校验 15位 CRC 17/21位 CRC(更强)
向后兼容 可与CAN 2.0节点共存

这里有个坑,我提醒你一下:CAN FD的节点可以和CAN 2.0节点挂在同一总线上,但前提是——所有节点都得支持CAN FD的“快速数据段”。否则,老节点会误判帧格式,直接报错。我曾经在一个混合总线上吃过这个亏,排查了整整两天。

核心区别一句话:CAN 2.0是“小包慢递”,CAN FD是“大包快送”。飞控里如果需要传输日志或固件升级,CAN FD优势明显。

3.2 帧结构:数据到底怎么装进去的?

帧结构这东西,说白了就是“数据包的格式”。CAN总线上跑的数据,都按这个格式打包。咱们以最常用的数据帧为例。

一个标准数据帧,由这些部分组成:

  • SOF(起始帧):1个显性位,告诉所有节点“我要开始说话了”。
  • 仲裁场:11位ID(标准帧)或29位ID(扩展帧),加上RTR位。这个ID决定了优先级。
  • 控制场:IDE位、保留位、DLC(数据长度码)。DLC告诉你后面跟了几个字节。
  • 数据场:0~8字节(CAN 2.0)或0~64字节(CAN FD)。
  • CRC场:校验数据完整性。
  • ACK场:接收节点确认收到。
  • EOF:7个隐性位,帧结束。

嗯,这里有个细节我特别想强调:DLC编码。CAN 2.0里DLC是4位,0~8对应0~8字节。但CAN FD里,DLC编码变了。比如DLC=9,对应12字节;DLC=15,对应64字节。你要是用老眼光看新协议,解析数据会全乱套。

我的习惯:在代码里写一个DLC解码函数,专门把CAN FD的DLC转成实际字节数。别偷懒,这个函数能救你一命。

3.3 仲裁机制:谁先说话?

CAN总线是“多主”架构。什么意思?就是所有节点都能随时发数据。那问题来了:如果两个节点同时发,谁说了算?

答案是:ID小的说了算

仲裁机制,说白了就是“按位比较ID”。每个节点在发送仲裁场时,会同时监听总线电平。如果自己发的是隐性位(1),但总线上是显性位(0),说明有更高优先级的节点在发数据。这时候,自己就乖乖退出发送,转为接收。

我举个例子:

  • 节点A的ID = 0x100
  • 节点B的ID = 0x200

二进制展开:

  • 0x100 = 0001 0000 0000
  • 0x200 = 0010 0000 0000

从高位开始比。第1位都是0,没问题。第2位,A是0,B是1。A发显性位(0),B发隐性位(1)。总线被A拉低,B检测到总线与自己发送不一致,立刻退出。A胜出,继续发送。

避坑指南:我曾经在飞控里把电机控制帧的ID设成了0x001,结果它总是抢在传感器数据帧(ID=0x010)之前发送。电机控制频率太高,传感器数据一直被延迟,导致姿态估计不准。后来我把传感器ID改成了0x001,电机控制改成0x010,问题解决。记住:关键数据用低ID

3.4 位时序配置:让所有节点“同步”

位时序,这是CAN总线里最容易出问题的地方。我见过太多工程师在这里翻车。

CAN总线的位时序,就是把一个位的时间分成若干段:

  • 同步段(Sync_Seg):1个时间量子(Tq)。用于同步各节点的时钟。
  • 传播段(Prop_Seg):补偿物理延迟。通常1~8 Tq。
  • 相位缓冲段1(Phase_Seg1):用于采样点前的调整。通常1~8 Tq。
  • 相位缓冲段2(Phase_Seg2):采样点后的调整。通常1~8 Tq。
  • 采样点(Sample Point):通常在Phase_Seg1结束时。

一个位的时间 = Sync_Seg + Prop_Seg + Phase_Seg1 + Phase_Seg2。

采样点的位置,决定了你什么时候去读总线电平。这个位置很关键。我一般把采样点设在87.5%左右。为什么?因为总线有传输延迟,采样点太靠前,可能读到的是“旧数据”;太靠后,又可能来不及处理。

咱们看一个实际配置例子。假设系统时钟80 MHz,预分频器设为4,那么Tq = 4 / 80 MHz = 50 ns。目标波特率1 Mbps,一个位的时间 = 1 µs = 20 Tq。

配置如下:

Sync_Seg = 1 Tq
Prop_Seg = 7 Tq
Phase_Seg1 = 8 Tq
Phase_Seg2 = 4 Tq
采样点位置 = (1 + 7 + 8) / 20 = 80%

这个配置在大多数飞控场景下是稳定的。但如果你总线很长(比如超过1米),或者节点数很多(超过10个),我建议把Prop_Seg加大到10 Tq以上。

注意:所有节点的位时序配置必须一致。否则,一个节点在采样点读到的是0,另一个节点读到的是1,直接导致CRC错误和错误帧。我曾经在调试时,两个飞控板用了不同的晶振,位时序差了一点点,结果总线上一堆错误帧。最后用示波器量了才发现。

3.5 知识体系总览

为了让你更直观地理解这一节的内容,我画了一张图。它把CAN 2.0和CAN FD的差异、帧结构、仲裁机制、位时序配置串在了一起。你可以把它当作一个“知识地图”。

CAN总线知识体系总览 CAN 2.0 vs CAN FD • 数据长度:8字节 vs 64字节 • 速率:1 Mbps vs 8 Mbps • CRC:15位 vs 17/21位 • 兼容性:CAN FD可共存 → 核心:大包快送 帧结构 • SOF → 仲裁场 → 控制场 • 数据场 → CRC → ACK → EOF • DLC编码:CAN 2.0 vs FD不同 • 标准帧11位ID,扩展帧29位 → 关键:DLC解码别搞错 仲裁机制 • 多主架构:谁都能发 • 按位比较ID,ID小优先 • 隐性位 vs 显性位 • 失败节点自动转为接收 → 关键数据用低ID 位时序配置 • Sync_Seg + Prop_Seg • Phase_Seg1 + Phase_Seg2 • 采样点:建议87.5% • 所有节点必须一致 → 翻车重灾区

这张图把四个核心模块串起来了。你从上往下看:先搞清楚CAN 2.0和CAN FD的差异,再理解帧结构怎么装数据,然后看仲裁机制怎么抢总线,最后搞定位时序让所有节点同步。每一步都是环环相扣的。

好了,CAN总线的内容就讲到这里。记住:帧结构是基础,仲裁是灵魂,位时序是命门。下次你调飞控总线时,按这个顺序排查,基本不会跑偏。


公众号:蓝海资料掘金营,微信deep3321