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 2.0和CAN FD的差异,再理解帧结构怎么装数据,然后看仲裁机制怎么抢总线,最后搞定位时序让所有节点同步。每一步都是环环相扣的。
好了,CAN总线的内容就讲到这里。记住:帧结构是基础,仲裁是灵魂,位时序是命门。下次你调飞控总线时,按这个顺序排查,基本不会跑偏。
公众号:蓝海资料掘金营,微信deep3321