3. CAN报文帧结构:数据帧、远程帧、错误帧、过载帧、帧间隔的详细解析
CAN总线上的所有通信行为都通过五种标准帧类型完成。理解每种帧的精确结构、仲裁机制和位填充规则,是诊断通信故障、设计高可靠工业节点的前提。本节逐一拆解五种帧的构成,并重点对比标准帧与扩展帧的差异。
3.1 帧类型概览与仲裁场
CAN 2.0B 规范定义了五种帧,其核心区别在于标识符长度和帧用途。下表列出各帧的基本功能与优先级(数值越小优先级越高)。
| 帧类型 | 功能 | 标识符长度 | 优先级(隐性位越多优先级越低) |
|---|---|---|---|
| 数据帧 | 发送节点向总线传输数据 | 11位(标准)或29位(扩展) | 由ID决定 |
| 远程帧 | 请求其他节点发送指定ID的数据帧 | 11位或29位 | 与同ID数据帧相同 |
| 错误帧 | 检测到总线错误时主动通知所有节点 | 无 | 最高(立即打断) |
| 过载帧 | 接收节点请求延迟下一数据帧/远程帧 | 无 | 次高 |
| 帧间隔 | 帧间分隔,总线空闲标志 | 无 | 最低(仅当总线空闲时出现) |
3.2 数据帧(Data Frame)
数据帧是CAN总线最常用的帧类型,负责将最多8字节数据从发送节点传输到所有接收节点。其结构分为七个场:帧起始、仲裁场、控制场、数据场、CRC场、ACK场、帧结束。
3.2.1 标准数据帧(11位ID)
标准数据帧的位序列如下(SOF为显性位“0”,EOF为7个隐性位“1”):
SOF | 11位标识符 | RTR | IDE | r0 | DLC(4位) | 数据(0~8字节) | CRC(15位) | CRC分隔符 | ACK槽 | ACK分隔符 | EOF(7位)
- SOF(1位):显性“0”,同步所有节点。
- 仲裁场(12位):11位标识符 + RTR位(数据帧RTR=0)。
- 控制场(6位):IDE位(标准帧IDE=0)+ r0保留位 + 4位DLC(数据长度码,0~8)。
- 数据场(0~64位):MSB优先发送。
- CRC场(16位):15位CRC + 1位隐性CRC分隔符。
- ACK场(2位):发送节点输出隐性“1”,接收节点在ACK槽写入显性“0”确认。
- EOF(7位):全部为隐性“1”。
3.2.2 扩展数据帧(29位ID)
扩展帧在仲裁场和控制场做了调整,以容纳更长的标识符:
SOF | 11位基本ID | SRR | IDE | 18位扩展ID | RTR | r1 | r0 | DLC(4位) | 数据 | CRC | CRC分隔符 | ACK槽 | ACK分隔符 | EOF
- SRR(1位):替代远程请求位,必须为隐性“1”。
- IDE(1位):扩展帧IDE=1,标识后续为18位扩展ID。
- 控制场(6位):r1 + r0两个保留位 + 4位DLC。
CAN_MO_MOCTR->IDE位。若误将扩展帧配置为标准帧,会导致仲裁失败和总线错误计数增加。
3.3 远程帧(Remote Frame)
远程帧用于请求数据,其结构与数据帧几乎相同,但有两个关键区别:
- RTR位为隐性“1”(数据帧为显性“0”)。
- 无数据场,DLC字段指示请求的数据长度,但实际不发送数据字节。
远程帧的仲裁规则:若总线上同时出现相同ID的数据帧和远程帧,数据帧因RTR=0而赢得仲裁。这意味着远程帧无法抢占同ID的数据帧,设计者需确保数据节点在收到远程帧后及时发送响应。
3.4 错误帧(Error Frame)
错误帧是CAN总线错误处理的核心机制。任何节点检测到总线错误后,立即发送错误帧,强制所有节点丢弃当前报文并重新同步。
3.4.1 错误帧结构
错误帧由两个场组成:
- 错误标志(Error Flag):6个连续相同位(显性“0”或隐性“1”)。
- 错误分隔符(Error Delimiter):8个隐性位“1”。
根据节点错误状态,错误标志分为两种:
| 节点状态 | 错误标志类型 | 位模式 | 说明 |
|---|---|---|---|
| 主动错误 | 主动错误标志 | 6个显性位“000000” | 强制打断当前报文,所有节点检测到位填充/CRC/格式错误 |
| 被动错误 | 被动错误标志 | 6个隐性位“111111” | 不破坏总线,仅当其他节点发送主动错误标志时才能被识别 |
CAN_MO_MOCTR->RXU0和CAN_MO_MOCTR->RXU1状态位可读取错误计数器。若发送错误计数(TEC)超过127,节点状态从“主动错误”切换为“被动错误”,此时错误帧不再包含显性位,可能导致总线无法及时清除错误报文。这是工业现场“总线锁死”的常见原因之一。
3.5 过载帧(Overload Frame)
过载帧用于接收节点在自身处理能力不足时,请求延迟下一个数据帧或远程帧的发送。其结构与错误帧类似:
- 过载标志(Overload Flag):6个显性位“000000”。
- 过载分隔符(Overload Delimiter):8个隐性位“11111111”。
过载帧的触发条件:
- 接收节点在帧间隔的第一位(间歇场)检测到显性位。
- 接收节点在EOF的最后一位采样到显性位(格式错误)。
- 接收节点内部缓冲区满,主动请求延迟。
CAN_MO_MOCTR->OVL位使能自动过载帧发送,防止接收溢出。
3.6 帧间隔(Interframe Space)
帧间隔用于分隔数据帧/远程帧与后续帧,确保总线状态清晰。其结构因节点状态而异:
| 节点状态 | 帧间隔组成 | 位长度 |
|---|---|---|
| 主动错误节点 | 间歇场(3位隐性)+ 总线空闲(任意长度隐性) | ≥3位 |
| 被动错误节点 | 间歇场(3位隐性)+ 暂停场(8位隐性)+ 总线空闲 | ≥11位 |
- 间歇场(Intermission):3个隐性位,禁止在间歇场发送数据帧/远程帧。
- 暂停场(Suspend Transmission):仅被动错误节点在间歇场后额外插入8个隐性位,给主动错误节点优先发送机会。
- 总线空闲(Bus Idle):任意长度的隐性位,任何节点检测到至少11个连续隐性位后即可开始发送。
3.7 帧结构综合对比SVG
下图以标准数据帧为基准,对比远程帧、错误帧、过载帧和帧间隔的位序列差异:
3.8 位填充机制与帧完整性
CAN总线采用位填充(Bit Stuffing)规则来保证时钟同步:在SOF到CRC场之间,若连续出现5个相同位,发送节点自动插入一个相反位。接收节点在解码时自动移除填充位。
- 填充位插入:每5个相同位后插入1个反相位。
- 填充位检测:若接收节点在6个连续位中未检测到电平变化,则判定为位填充错误,立即发送错误帧。
- 例外区域:CRC分隔符、ACK场、EOF、间歇场、错误/过载标志不进行位填充。
CAN_MO_MOCTR->STF状态位可查询位填充错误。若频繁出现填充错误,应检查总线位定时配置(尤其是采样点位置)和总线终端电阻(标准120Ω)。错误的采样点会导致边缘采样偏差,误判连续位。
3.9 帧结构在XMC中的配置示例
以下代码展示如何在XMC4500的MultiCAN+模块中配置一个标准数据帧对象(11位ID,DLC=8,发送模式):
/* XMC4500 MultiCAN+ 标准数据帧配置示例 */
#include <xmc_can.h>
/* 定义CAN节点和报文对象 */
XMC_CAN_t *can_node = XMC_CAN0;
uint8_t mo_number = 1;
/* 配置报文对象为发送数据帧 */
XMC_CAN_MO_t mo_config = {
.can_mo_ptr = XMC_CAN0_MO1,
.can_node = can_node,
.mo_type = XMC_CAN_MO_TYPE_TRANSMSGOBJ,
.id_mode = XMC_CAN_FRAME_TYPE_STANDARD_11B,
.id = 0x123, /* 11位标识符 */
.dlc = 8, /* 数据长度8字节 */
.ide = 0, /* 标准帧 */
.rtr = 0 /* 数据帧 */
};
/* 初始化报文对象 */
XMC_CAN_MO_Init(&mo_config);
/* 设置发送数据缓冲区 */
uint8_t tx_data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
XMC_CAN_MO_UpdateData(&mo_config, tx_data);
/* 请求发送 */
XMC_CAN_MO_Transmit(&mo_config);
id_mode误设为XMC_CAN_FRAME_TYPE_EXTENDED_29B但实际发送11位ID,总线上的扩展帧接收节点将无法识别该报文,导致ACK缺失和发送错误计数上升。务必在初始化前确认IDE位与标识符长度的一致性。
3.10 帧类型与错误状态的关系
错误帧和过载帧的发送时机与节点错误状态密切相关。下表总结不同状态下各帧的发送行为:
| 节点状态 | 发送数据帧/远程帧 | 发送错误帧 | 发送过载帧 | 帧间隔暂停场 |
|---|---|---|---|---|
| 主动错误 | 正常 | 主动错误标志(6显性) | 正常 | 无 |
| 被动错误 | 正常(但发送后需等待8位暂停) | 被动错误标志(6隐性) | 正常 | 有(8位隐性) |
| 总线关闭 | 禁止发送 | 禁止发送 | 禁止发送 | 不参与 |
在XMC系列中,通过读取CAN_NSR->LEC(最后错误代码)寄存器可快速定位错误类型:
- LEC=1:位填充错误
- LEC=2:格式错误
- LEC=3:ACK错误
- LEC=4:隐性位错误
- LEC=5:显性位错误
- LEC=6:CRC错误
- LEC=7:无错误
CAN_NSR->TEC和CAN_NSR->REC错误计数器,若TEC快速上升至127以上,说明发送节点存在硬件故障(如驱动器短路或时钟偏差过大)。