2. CAN报文结构详解

CAN(Controller Area Network)报文是总线通信的基本数据单元。理解报文结构是进行ID过滤、DLC校验和数据解析的前提。本章将深入剖析标准帧与扩展帧的位域组成,重点对比仲裁场中11位ID与29位ID的差异,并解析DLC与数据场的编码规则。

2.1 标准帧与扩展帧的帧格式对比

CAN协议定义了两种帧格式:标准帧(CAN 2.0A)和扩展帧(CAN 2.0B)。两者在仲裁场长度、ID位数和DLC位置上有显著区别。下表列出了核心差异:

对比项 标准帧 (Base Frame) 扩展帧 (Extended Frame)
ID 位数 11 位 (ID10 ~ ID0) 29 位 (ID28 ~ ID0)
仲裁场长度 12 位 (SOF + 11 ID + RTR + IDE) 32 位 (SOF + 11 Base ID + SRR + IDE + 18 Ext ID + RTR)
IDE 位 显性 (0) 隐性 (1)
SRR 位 无 隐性 (1),替代标准帧RTR位置
DLC 位置 控制场第1~4位 控制场第1~4位(与标准帧相同)
最大数据长度 8 字节 8 字节
总线利用率 较高(帧头开销小) 较低(帧头多20位)
实战提示:在MCU驱动开发中,标准帧常用于实时性要求高、节点数少的系统(如电机控制);扩展帧多用于车载网络(如J1939协议),需要更多ID空间来区分大量ECU和信号。

2.2 标准帧位域逐段解析

标准帧由7个场组成:SOF、仲裁场、控制场、数据场、CRC场、ACK场、EOF。下图展示了标准帧的完整位布局:

标准帧 (CAN 2.0A) 位域结构 SOF 1 bit 仲裁场 (12 bits) 11位ID + RTR + IDE 12 bits 控制场 DLC + r0/r1 6 bits 数据场 0~8 字节 0~64 bits CRC场 CRC + Delim 16 bits ACK Slot+Delim 2 bits EOF 7 bits 7 bits 关键位域说明: • SOF (Start of Frame):1位显性位,同步所有节点。 • 仲裁场:11位ID + RTR (远程帧请求) + IDE (标识符扩展位,标准帧为0)。 • 控制场:r1/r0 (保留位) + DLC (数据长度码,4位,表示数据场字节数)。 • 数据场:0~8字节,实际载荷数据。 • CRC场:15位CRC校验 + 1位CRC界定符。 • ACK场:1位ACK槽 + 1位ACK界定符。 • EOF (End of Frame):7位隐性位,标志帧结束。

2.3 扩展帧位域逐段解析

扩展帧在仲裁场中增加了18位扩展ID,使ID总数达到29位。其仲裁场结构更复杂,包含SRR位和IDE位。下图展示了扩展帧的位布局:

扩展帧 (CAN 2.0B) 位域结构 SOF 1 bit 仲裁场 (32 bits) 11位Base ID + SRR + IDE + 18位Ext ID + RTR 32 bits 控制场 DLC + r0/r1 6 bits 数据场 0~8 字节 0~64 bits CRC场 CRC+Delim 16 bits ACK 2 bits 2 bits EOF 7 bits 扩展帧仲裁场特殊位: • SRR (Substitute Remote Request):1位隐性位,替代标准帧的RTR位置。当标准帧与扩展帧同时发送时,标准帧的显性RTR会赢得仲裁。 • IDE (Identifier Extension):1位隐性位 (1),表示当前帧为扩展帧。标准帧的IDE为显性 (0)。 • 扩展ID (18 bits):位于IDE之后,与11位Base ID共同构成29位ID。 • RTR (Remote Transmission Request):位于仲裁场末尾,决定帧类型(数据帧/远程帧)。 • 注意:扩展帧的DLC、数据场、CRC、ACK、EOF与标准帧完全一致。

2.4 ID结构与优先级仲裁

CAN总线采用逐位仲裁机制,ID数值越小,优先级越高。标准帧的11位ID范围是 0x000 ~ 0x7FF(2048个ID),扩展帧的29位ID范围是 0x00000000 ~ 0x1FFFFFFF(约5.36亿个ID)。

仲裁规则:
  • 显性位 (0) 覆盖隐性位 (1)。
  • 标准帧的IDE为显性 (0),扩展帧的IDE为隐性 (1),因此标准帧在IDE位赢得仲裁。
  • 当标准帧与扩展帧ID相同时,标准帧优先发送。
  • 扩展帧之间比较29位ID,数值小的优先。

2.5 DLC与数据场编码规则

DLC(Data Length Code)位于控制场,占用4位,编码方式如下:

DLC 值 (二进制) DLC 值 (十进制) 数据场字节数 说明
0000 0 0 无数据,远程帧常用
0001 1 1 单字节数据
0010 2 2 双字节数据
0011 3 3 三字节数据
0100 4 4 四字节数据
0101 5 5 五字节数据
0110 6 6 六字节数据
0111 7 7 七字节数据
1000 ~ 1111 8 ~ 15 8 DLC≥8时,数据场固定为8字节
驱动开发注意:DLC值大于8时,CAN控制器仍会发送/接收8字节数据。在MCU驱动中,必须根据DLC值截取有效数据,避免将无效字节误判为有效信号。例如,DLC=3时,只解析数据场前3个字节。

2.6 数据场字节序与位填充

数据场最多8字节,字节序(Endianness)由应用层协议定义。CAN协议本身不规定字节序,但常见约定如下:

  • Motorola格式(大端序):高字节在前,低字节在后。例如16位信号 0x1234,Byte0=0x12,Byte1=0x34。
  • Intel格式(小端序):低字节在前,高字节在后。例如16位信号 0x1234,Byte0=0x34,Byte1=0x12。

此外,CAN总线使用位填充机制:连续5个相同位后自动插入一个相反位,确保时钟同步。位填充不影响ID、DLC和数据场的逻辑值,但会增加帧长度。标准帧最大位数为111位(含填充),扩展帧最大位数为131位(含填充)。

2.7 报文解析实战示例

假设MCU从CAN控制器接收缓冲区读取到以下原始数据(以标准帧为例):

// 原始CAN帧数据(假设从硬件寄存器读取)
uint32_t id = 0x123;          // 11位ID
uint8_t  dlc = 0x04;          // DLC = 4
uint8_t  data[8] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x00, 0x00, 0x00};
uint8_t  ide = 0;             // 标准帧
uint8_t  rtr = 0;             // 数据帧

解析步骤:

  1. ID提取: id = 0x123,对应二进制 0001 0010 0011,优先级较高。
  2. DLC校验: dlc = 4,有效数据长度为4字节。
  3. 数据场解析: data[0] ~ data[3] 为有效数据,data[4] ~ data[7] 忽略。
  4. 帧类型判断: ide = 0 且 rtr = 0,为标准数据帧。