CAN自定义协议
本标准旨在为基于 CAN FD 总线的嵌入式系统提供一套可复用的应用层协议设计指南。适用于主从架构或多节点分布式系统中,对数据吞吐量、实时性、可扩展性有明确要求的场景。
1. 范围与目的
本标准规定了基于 CAN FD 物理层与数据链路层的应用层协议设计方法,包括:
- 协议架构与分层
- 标识符分配策略
- 数据帧格式
- 时间同步机制
- 传输层协议(分片与重组)
- 网络管理
- 错误处理与诊断
- 测试与验证要求
2. 规范性引用文件
- ISO 11898-1:2015(CAN FD 数据链路层)
- CiA 601(CAN FD 应用层设计建议)
3. 术语与定义
| 术语 | 定义 |
|---|---|
| 上行 | 从设备端(MCU、传感器)发往主机端(Linux、PC)的数据流 |
| 下行 | 从主机端发往设备端的控制或配置数据流 |
| seq | 同步序号,用于关联同一周期或同一事务的多帧数据 |
| 锚点 | 外部同步事件(如FSIN、软件定时器)产生的时刻标记 |
| 分片 | 将超过单帧最大载荷的业务数据拆分为多帧发送 |
| 通用头 | 所有业务帧共用的固定头部,包含版本、类型、序号等 |
4. 协议设计原则
- 分层清晰:协议应至少划分为“帧格式层”与“业务载荷层”,便于维护与扩展。
- 时间确定性:关键数据应携带硬件时间戳,时间源统一为单调时钟(us级)。
- 可扩展性:通过版本号、保留字段、消息类型扩展机制支持未来升级。
- 紧凑性:充分利用 CAN FD 64 字节数据场,避免带宽浪费。
- 容错性:定义错误标志、降级策略与心跳监控,确保系统可诊断。
- 兼容性:若网络中存在传统 CAN 节点,CAN FD 帧须禁用 BRS 或使用独立 ID 空间。
5. 物理层与数据链路层配置
5.1 位速率选择
- 仲裁段(Nominal):典型值 500 kbps 或 1 Mbps。用于总线仲裁,应保证所有节点一致。
- 数据段(Data):典型值 2 Mbps、4 Mbps、8 Mbps。依据线束长度、节点数量、EMC 环境选择,启用 BRS(波特率切换)。
5.2 位时序计算
- 依据控制器时钟频率(如 STM32G431 的 FDCAN 时钟 170 MHz)计算预分频器、时间片段。
- 采样点建议:仲裁段 70%~80%,数据段 75%~85%。
- 同步跳转宽度(SJW)建议设为 1~3,保证抗干扰能力。
5.3 接收过滤
- 根据节点数量配置硬件过滤器(标准 ID 或扩展 ID 掩码)。
- 开发阶段可设置为接收全部 ID(过滤器数量为 0);量产阶段按 ID 段过滤,减少无关中断。
5.4 自动重发
- 高可靠性场景建议开启自动重发(AutoRetransmission = ENABLE)。
- 若关闭,则应用层须实现超时重传机制。
6. 标识符(ID)规划
6.1 ID 类型选择
- 标准 ID(11-bit):节点数 ≤ 128,消息类型较少时使用。
- 扩展 ID(29-bit):多节点、多功能、需要嵌入节点地址或功能码时使用。
6.2 ID 分段策略
将 ID 空间按优先级、方向、功能划分。例如:
| 位域 | 长度 | 含义 |
|---|---|---|
| 优先级 | 3-bit | 0(最高)~7(最低) |
| 方向 | 1-bit | 0=上行,1=下行 |
| 功能码 | 4-bit | 具体消息类型 |
| 节点地址 | 3-bit | 目标或源节点号 |
或使用更简单的分段:
- 上行:
0x100 ~ 0x17F - 下行:
0x180 ~ 0x1FF
6.3 预留与扩展
- 保留 10%~20% ID 空间用于未来扩展。
- 若使用扩展 ID,保留高位用于设备型号或版本标识。
7. 数据帧格式
7.1 通用头部(8 字节固定)
所有业务帧载荷的前 8 字节采用统一格式:
| 字节偏移 | 字段 | 类型 | 说明 |
|---|---|---|---|
| 0 | proto_ver | uint8_t | 协议版本号 |
| 1 | msg_type | uint8_t | 消息类型(见 7.2) |
| 2 | flags | uint8_t | 标志位:bit0=分片,bit1=ACK请求,bit2=错误帧 |
| 3 | hdr_len | uint8_t | 头长度(固定 8) |
| 4-5 | seq | uint16_t | 同步序号(或事务序号) |
| 6 | part_idx | uint8_t | 分片索引,从 0 开始 |
| 7 | part_cnt | uint8_t | 总分片数,单帧为 1 |
字节序:小端(Little-Endian)。
7.2 消息类型(msg_type)定义
| 类型值 | 方向 | 含义 |
|---|---|---|
| 0x01 | 上行 | 同步锚点 |
| 0x02 | 上行 | IMU 数据 |
| 0x03 | 上行 | 编码器数据 |
| 0x04 | 上行 | 系统状态 |
| 0x81 | 下行 | 控制命令 |
| 0x82 | 下行 | 参数配置 |
| 0x8F | 下行 | 链路测试(Ping) |
| 0xFF | 任意 | 厂商调试 |
7.3 业务载荷定义
每种消息类型紧跟通用头定义其私有载荷。设计原则:
- 使用紧凑型结构(
__attribute__((packed))或#pragma pack(1)) - 整数采用缩放表示(如 s16 表示角速度,精度 0.01 dps)代替浮点,节省带宽
- 预留 2~8 字节保留字段供后续扩展
- 总载荷长度建议不超过 64 字节(CAN FD 数据场最大值)
示例(IMU 数据载荷):
struct imu_payload {
uint64_t ts_us; // 采样时间戳(us)
int16_t gyro[3]; // 陀螺仪,单位 mdps
int16_t acc[3]; // 加速度计,单位 mg
uint8_t src; // 传感器源
uint8_t quality; // 质量标志
uint8_t reserved[2]; // 对齐保留
};
7.4 时间戳策略
- 统一时钟源:所有时间戳使用 MCU 单调时钟(us),避免使用上位机时间戳。
- 锚点同步:对于周期性外部触发系统,单独发送锚点帧记录触发时刻;数据帧携带各自采样时刻,上位机通过比对获得精确时序。
- 无锚点系统:可直接在每个数据帧中携带采样时刻。
8. 传输层协议(分片与重组)
当单条业务消息载荷超过 64 字节(CAN FD 最大数据场)时,需进行分片传输。
8.1 分片规则
- 发送端设置
flags.bit0 = 1 part_cnt记录总分片数part_idx从 0 递增- 所有分片使用相同的
seq和msg_type - 分片间隔应尽可能短,避免接收端超时
8.2 重组规则
- 接收端根据
(seq, msg_type)维护重组缓冲区 - 超时未收齐所有分片则丢弃该消息并记录错误(建 议超时时间 5~20 ms)
- 支持乱序到达(根据
part_idx重组) - 重复分片以首次到达为准,后续丢弃
8.3 流控(可选)
对于大文件传输(如固件升级),可定义流控制帧:
- 接收端发送流控帧通知发送端窗口大小、间隔时间
- 发送端依据流控参数调节发送速率,防止接收端缓冲区溢出
9. 网络管理
9.1 心跳机制
- 每个节点周期性(如 10 Hz)发送状态帧(如 SYS_STATUS)
- 状态帧包含:运行时间、错误标志、供电电压、温度、丢包计数等
- 主机若超过 N 个周期未收到从机心跳,判定从机离线并触发故障保护
9.2 在线诊断
- 下行命令支持请求状态立即上报(如 CMD_CTRL 中 cmd_id=0x04)
- 支持链路测试(Ping/Pong),可用于计算往返时延(RTT)
9.3 负载管理
- 预先定义数据流优先级,当总线负载超过阈值时,自动降低非关键数据发送频率
- 优先级顺序建议:同步锚点 > 控制命令 > 关键传感器数据 > 状态 > 非周期配置
10. 错误处理与安全
10.1 错误标志
在状态帧中定义错误位图,至少包括:
- 传感器 FIFO 溢出
- 时间戳回退
- CAN 发送队列满
- CAN ACK 错误
- 配置参数非法
10.2 端到端保护
对关键控制命令(如电机启停、参数写入)可增加:
- 计数器(防止重放)
- 超时监控(命令必须在一定时间内完成)
- 应用层 CRC(可选,用于高安全等级)
10.3 降级策略
当检测到严重错误(如 CAN 总线关闭、传感器故障 )时,节点应自动进入安全状态,并持续发送错误状态帧。
11. 版本管理与扩展性
11.1 协议版本号
- 主版本号变更:协议布局不兼容
- 次版本号变更:新增字段且向后兼容(旧版本忽略未知字段)
- 版本号置于通用头
proto_ver字段
11.2 字段扩展
- 每个载荷结构预留 2~8 字节保留字段
- 新增字段应尽量放在载荷尾部,并更新
hdr_len(如头部变化)或使用保留字段
11.3 消息类型扩展
msg_type使用 8 位,0x000x7F 用于上行,0x800xFF 用于下行(或相反)- 保留 0xF0~0xFF 为厂商自定义类型
12. 测试与验证要求
- 最小可行产品(MVP):先实现核心消息类型(如锚点、传感器数据、状态、Ping),验证物理层配置和基本通信。
- 总线负载测试:在最恶劣工况下计算理论负载率,实测确认无丢帧。
- 信号质量验证:使用示波器/逻辑分析仪检查数据段波形,确保上升沿、振铃在可接受范围。
- 兼容性测试:若与经典 CAN 节点共存,验证 CAN FD 节点在 BRS=0 时不会引起错误帧。
- 长期稳定性测试:连续运行 24 小时以上,检查丢包计数、错误标志是否正常。
- 分片与重组测试:模拟大数据块传输,验证超时重传、乱序重组功能。
13. 文档要求
协议设计应至少包含以下文档:
- 协议规范:描述 ID 分配、帧格式、消息类型、载荷定义。
- 实现指南:给出位时序计算示例、代码结构建议(如
proto.h、can_driver.c)。 - 测试报告:记录测试环境、测试项、结果及问题。
14. 附录:典型协议结构示例(参考)
| 方向 | ID | msg_type | 载荷 | 频率 |
|---|---|---|---|---|
| 上行 | 0x110 | 0x01 | 锚点时间 + 源 | 1 kHz |
| 上行 | 0x111 | 0x02 | IMU 数据(32B) | 1 kHz |
| 上行 | 0x112 | 0x03 | 编码器数据(32B) | 200 Hz |
| 上行 | 0x113 | 0x04 | 系统状态(24B) | 10 Hz |
| 下行 | 0x190 | 0x81 | 控制命令(8B) | 异步 |
| 下行 | 0x191 | 0x82 | 参数配置(16B) | 异步 |
| 下行 | 0x19F | 0x8F | Ping 请求(4B) | 按需 |
本通用标准可作为任何 CAN FD 自定义协议设计的起点,实际应用时可根据具体需求裁剪或扩展。