4. DroneCAN报文结构

DroneCAN 建立在经典 CAN 2.0B 之上,使用 29 位扩展帧标识符承载协议语义。理解报文结构,是后续抓包分析、故障定位和节点调试的基础。本节从帧类型、优先级、CAN ID 分配、多帧传输以及动态节点 ID 与即插即用机制五个方面展开,帮助你在 Wireshark 或 candump 中快速读懂每一帧的含义。

一、帧类型与 CAN ID 的位域划分

DroneCAN 的 29 位 CAN ID 并非随机分配,而是被划分为若干语义字段。标准格式如下:

29 位 CAN ID 位域(从高位到低位):
[28:25] 传输优先级 Priority   (0 最高,31 最低)
[24:16] 数据类型 Data Type ID (消息/服务类型编号)
[15:8]  源节点 ID Source Node ID
[7:0]   目标节点/保留字段
        - 广播消息:低 8 位为 0
        - 单播/服务:低 8 位为目标节点 ID
        - 匿名消息:使用特殊保留值

由此可以看出,DroneCAN 报文天然分为三类:广播消息(如 uavcan.protocol.NodeStatus)、单播消息(点对点传输)和服务请求/响应(Service)。此外还有一类特殊的匿名消息,用于节点在尚未获得 ID 时进行动态分配协商。

二、传输优先级

优先级字段位于 CAN ID 的最高位,数值越小优先级越高。CAN 总线仲裁时,ID 越小越先发送,因此 DroneCAN 通过优先级字段实现了确定性的实时调度。常见约定如下:

优先级值典型用途说明
0~3紧急安全消息如故障告警、急停指令
4~7实时控制执行器指令、姿态控制
8~15状态与遥测NodeStatus、传感器数据
16~23配置与参数参数读写、节点配置
24~31调试与日志非实时诊断信息
抓包时若发现某节点持续占用总线,优先检查其优先级字段是否被错误设置为 0,导致低优先级消息长期被压制。

三、多帧传输机制

CAN 单帧数据场最多 8 字节,而 DroneCAN 的许多消息(如固件升级、日志、大数组)远超此限制。为此 DroneCAN 定义了多帧传输协议,将长消息拆分为首帧、中间帧和尾帧,通过 CRC 校验保证完整性。

多帧传输结构:
首帧 Start Frame
  - 传输 ID、总长度、CRC 种子
中间帧 Middle Frame
  - 序号递增,携带数据片段
尾帧 End Frame
  - 最后数据 + CRC 校验值

接收方按传输 ID 重组,校验失败则丢弃整条消息

多帧传输的关键在于传输 ID,它使得同一总线上多个节点的多帧消息可以交错传输而不混淆。抓包分析时,应关注首帧中的总长度与后续帧序号是否连续,若出现序号跳跃或 CRC 错误,通常意味着总线干扰或节点发送异常。

四、动态节点 ID 与即插即用机制

DroneCAN 最实用的特性之一是动态节点 ID 分配。节点上电后若未配置固定 ID,会先发送匿名消息参与 ID 分配协商,通过唯一标识(如硬件 UUID)竞争一个空闲 ID。这一过程无需人工干预,实现了即插即用。

分配流程大致如下:

  1. 节点上电,检测自身是否已有固定 ID;
  2. 若无,则发送匿名 NodeStatus 广播,声明自身存在;
  3. 总线上的分配器(通常是飞控)根据 UUID 和当前占用情况,分配一个空闲 ID;
  4. 节点收到分配结果后,切换到该 ID 并开始正常通信;
  5. 若发生冲突,节点重新进入匿名状态并再次协商。
动态 ID 分配依赖总线上的分配器正常工作。若飞控未启动或分配器失效,新接入节点将无法获得 ID,表现为“节点在线但无数据”。此时应检查分配器状态或手动配置固定 ID。

五、综合案例与抓包判读

假设你在抓包中看到如下 CAN ID:0x0C7A0123。按位域拆解:

0x0C7A0123 = 二进制 0 1100 0111 1010 0000 0001 0010 0011
优先级   = 0b00110 = 6
数据类型 = 0b001111010 = 0x7A
源节点   = 0x01
目标/保留 = 0x23

由此可判断:这是一条优先级为 6 的实时控制类消息,源节点 ID 为 1,低 8 位非零,说明是单播或服务响应。结合数据类型编号查表,即可确定具体消息名称。

常见误区包括:把 CAN ID 当作纯编号记忆而忽略位域含义;在多帧传输中只看单帧数据而忽略重组;以及认为动态 ID 分配一定成功。复盘时应养成“先拆位域、再看类型、后查多帧”的判读习惯。

DroneCAN 29 位 CAN ID 位域与报文类型 优先级 [28:25] 数据类型 ID [24:16] 源节点 ID [15:8] 目标/保留 [7:0] 低 8 位决定报文类型 广播消息 低 8 位 = 0 单播消息 低 8 位 = 目标 ID 服务请求/响应 低 8 位 = 目标 ID 匿名消息 特殊保留值 多帧传输:首帧 → 中间帧 → 尾帧 首帧 传输ID + 总长度 + CRC种子 中间帧 序号递增 + 数据片段 尾帧 最后数据 + CRC校验 动态节点 ID 分配:上电 → 匿名广播 → 分配器协商 → 获得 ID → 正常通信 冲突时重新进入匿名状态,实现即插即用