2. CAN报文结构详解:标准帧与扩展帧、数据帧、远程帧、错误帧、过载帧、帧间隔
CAN协议定义了五种基本帧类型和一种帧间隔结构,理解这些帧的格式与用途是进行报文过滤与ID分配优化的前提。本章将逐一拆解每种帧的位域结构、仲裁机制及应用场景。
2.1 标准帧与扩展帧:ID长度的差异
CAN 2.0A(标准帧)使用11位标识符(ID),CAN 2.0B(扩展帧)使用29位标识符。两者在仲裁场和帧结构上存在关键区别。
| 特性 | 标准帧(Base Frame) | 扩展帧(Extended Frame) |
|---|---|---|
| ID长度 | 11位 | 29位 |
| IDE位 | 显性(0) | 隐性(1) |
| SRR位 | 无 | 替代远程请求位(隐性) |
| 仲裁场长度 | 12位(ID + RTR) | 32位(ID + SRR + IDE + RTR) |
| 数据场最大长度 | 8字节 | 8字节 |
| 总线利用率 | 较高(帧头短) | 较低(帧头多21位) |
| 典型应用 | 动力总成、车身控制 | ADAS、信息娱乐、多ECU系统 |
关键点:标准帧与扩展帧可以共存于同一总线。当标准帧与扩展帧ID高位相同时,标准帧因IDE位显性而获得更高优先级。在报文过滤配置中,必须明确指定帧类型(标准/扩展),否则硬件过滤器可能无法正确匹配。
2.2 数据帧:承载应用信息的核心帧
数据帧是CAN总线最常用的帧类型,用于从发送节点向一个或多个接收节点传输数据。其完整结构包含七个场:帧起始、仲裁场、控制场、数据场、CRC场、ACK场、帧结束。
2.3 远程帧:请求数据而不发送数据
远程帧用于一个节点主动请求另一个节点发送数据。其结构与数据帧几乎相同,但RTR位为隐性(1),且数据场为空(DLC指示期望接收的数据长度)。
远程帧 vs 数据帧对比:
- RTR位:数据帧为显性(0),远程帧为隐性(1)。
- 数据场:数据帧包含0~8字节数据;远程帧无数据场。
- 优先级:相同ID下,数据帧优先级高于远程帧(RTR显性优先)。
- 典型场景:传感器节点收到远程帧后,采集数据并以数据帧回复。
2.4 错误帧:总线错误通知机制
当任何节点检测到总线错误时,立即发送错误帧,通知所有节点丢弃当前报文。错误帧由错误标志和错误定界符组成。
| 错误类型 | 触发条件 | 错误标志长度 |
|---|---|---|
| 位错误 | 发送节点监控到总线电平与发送电平不一致 | 6位显性位 |
| 填充错误 | 检测到连续6个相同电平位(违反位填充规则) | 6位显性位 |
| CRC错误 | 接收节点计算的CRC与发送CRC不匹配 | 6位显性位 |
| 形式错误 | 固定格式位(如EOF、定界符)出现错误电平 | 6位显性位 |
| 应答错误 | 发送节点在ACK槽未检测到显性位 | 6位显性位 |
工程注意:错误帧的发送会导致总线进入错误恢复流程。频繁的错误帧表明总线物理层或节点时序存在问题。在报文过滤与ID分配优化中,应避免ID冲突导致的位错误,以及DLC不匹配导致的CRC错误。
2.5 过载帧:接收节点请求延迟
过载帧由接收节点在以下两种情况下发送:
- 节点内部条件未准备好,无法开始接收下一帧。
- 在帧间隔期间检测到显性位(非法情况)。
过载帧结构:6位显性过载标志 + 8位隐性过载定界符。过载帧与错误帧的区别在于:过载帧不增加错误计数器,且仅在帧间隔期间发送。
2.6 帧间隔:总线空闲与优先级重置
帧间隔(Interframe Space)用于将前一帧与后续帧分隔开,确保总线状态稳定。帧间隔包含三个场:
2.7 帧类型识别与过滤配置要点
在MCU外设驱动开发中,CAN控制器硬件过滤器需要根据帧类型进行配置。以下是关键配置参数:
/* 标准帧过滤器配置示例(以STM32 bxCAN为例) */
CAN_FilterInitTypeDef filter;
filter.FilterIdHigh = (id << 5) >> 16; // 11位ID左对齐
filter.FilterIdLow = (id << 5) & 0xFFFF;
filter.FilterMaskIdHigh = (mask << 5) >> 16;
filter.FilterMaskIdLow = (mask << 5) & 0xFFFF;
filter.FilterScale = CAN_FilterScale_16bit;
filter.FilterMode = CAN_FilterMode_IdMask;
filter.FilterFIFOAssignment = CAN_FIFO0;
filter.FilterActivation = ENABLE;
/* 注意:标准帧需设置 FilterBank 的 IDE 位为 0 */
/* 扩展帧过滤器配置示例 */
filter.FilterIdHigh = (id >> 13) & 0xFFFF; // 29位ID高16位
filter.FilterIdLow = (id << 3) & 0xFFF8; // 低13位 + IDE位(1) + RTR位
filter.FilterMaskIdHigh = (mask >> 13) & 0xFFFF;
filter.FilterMaskIdLow = (mask << 3) & 0xFFF8;
/* 注意:扩展帧必须设置 IDE 位为 1,否则过滤器无法匹配 */
优化建议:在ID分配阶段,建议将标准帧与扩展帧的ID空间分开规划。例如,标准帧ID范围0x000~0x7FF用于高优先级实时控制,扩展帧ID范围0x10000000~0x1FFFFFFF用于诊断和配置。这样可以在硬件过滤器中设置两个独立的过滤器组,分别匹配标准帧和扩展帧,降低CPU负载。
2.8 帧结构对ID分配的影响
理解帧结构后,可以总结出ID分配优化的几个关键约束:
- 优先级与ID值:ID值越小,优先级越高。关键安全报文(如制动、转向)应分配小ID。
- 标准帧 vs 扩展帧:标准帧ID空间有限(2048个),扩展帧ID空间充裕(约5.3亿个)。在大型网络中,优先使用扩展帧以避免ID冲突。
- RTR位影响:远程帧的RTR位为隐性,导致其优先级低于同ID的数据帧。设计时应避免数据帧与远程帧使用相同ID,否则可能引发优先级反转。
- DLC与数据场:DLC必须与实际数据长度一致。过大的DLC浪费总线带宽,过小的DLC可能导致接收节点数据截断。