CAN通信协议
CAN 是 Controller Area Network 的缩写,是1986年德国电气商博世公司开发出面向汽车的通信协议,相关协议为ISO11898 及 ISO11519,是汽车电子领域一种非常重要的协议。I2C和SPI用于板上厘米级距离内的通信,而CAN用于几米(最高1Mbps)至几十米距离内的通信(最远可达10KM,但速率低于5Kbps),不分主从。

CAN类似RS485通过差分信号传输数据。根据CAN总线上两根线的电位差来判断总线电平,总线电平分为显性电平和隐性电平,显性为0,隐性为1。
CAN协议包括5种类型的帧:
数据帧:发送单元向接收单元传送数据
遥控帧:接收单元向具有相同ID的发送单元请求数据
错误帧:某个节点检测出错误时向其它单元通知错误
过载帧:接收单元通知其尚未做好接收准备
间隔帧:将数据帧及遥控帧与前面的帧分离开来的帧
数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有 11 个位的标识符(ID),扩展格式有 29 个位的 ID。
数据帧一般由 7 个段构成:
帧起始。表示数据帧开始的段。
仲裁段。表示该帧优先级的段。
控制段。表示数据的字节数及保留位的段。
数据段。数据的内容,一帧可发送 0~8 个字节的数据。
CRC 段。检查帧的传输错误的段。
ACK 段。表示确认正常接收的段。
帧结束。表示数据帧结束的段。
标准帧格式如图:

| 字段名 | 字长 (位) | 作用 |
|---|---|---|
| 起始位(SOF) | 1 | 表示帧的传输开始 |
| 识别码(ID\green) | 11 | 唯一识别码,同样代表了优先级 |
| 远程传输请求(RTR\蓝色) | 1 | 数据帧是显性(0),远程请求帧是隐性(1) |
| 标志码拓展位(IDE) | 1 | 对于只有11位标志码的基本帧格式,此段为显性(0) |
| 预留位(R0) | 1 | 预留位一定是显性(0),但是隐性(1)同样是可接受的 |
| 数据长度代码(DLC\黄色) | 4 | 数据的字节数(0-8字节) |
| 数据段(Data field\红色) | 0–64 (0-8 字节) | 待传输数据(长度由数据长度码DLC指定) |
| 循环冗余校验(CRC) | 15 | 循环冗余校验 |
| 循环冗余校验定界码 | 1 | 隐性(1) |
| 确认槽(ACK) | 1 | 发信器发送隐性(1)其他接收节点可以发送显性(0) |
| 确认定界码(ACK delimiter) | 1 | 隐性(1) |
| 结束位(EOF) | 7 | 隐性(1) |
扩展帧格式:
| 字段名 | 字长 (位) | 作用 |
|---|---|---|
| 起始位(SOF) | 1 | 表示帧的传输开始 |
| 标志符A(ID A\green) | 11 | 唯一识别码的第一部分,代表优先级 |
| 替代远程请求(SRR) | 1 | 数据帧是显性(0),远程请求帧是隐性(1) |
| 标志符拓展位(IDE) | 1 | 有29位标志符的拓展帧格式,此段为隐性(1) |
| 标志符B(ID B\green) | 18 | 唯一识别码的第二部分,同样代表了优先级 |
| 远程传输请求(RTR\蓝色) | 1 | 数据帧是显性(0),远程请求帧是隐性(1) |
| 预留位(r1,r0) | 2 | 预留位是显性(0),但是隐性(1)同样是可接受的 |
| 数据长度代码(DLC\黄色) | 4 | 数据的字节数(0-8字节) |
| 数据段(Data field\红色) | 0–64 (0-8 字节) | 待传输数据(长度由数据长度码DLC指定) |
| 循环冗余校验(CRC) | 15 | 循环冗余校验 |
| 循环冗余校验定界符 | 1 | 隐性(1) |
| 确认槽(ACK) | 1 | 发送器发送隐性(1),其他接收节点可以发送显性(0) |
| 确认定界符(ACK delimiter) | 1 | 隐性(1) |
| 结束位(EOF) | 7 | 隐性(1) |
一个 CAN 位时间(Bit Time)由以下部分组成:
SYNC_SEG (同步段):固定 1 个时间量子(Tq),用于对齐发送端和接收端的位边界。
TSEG1 (时间段1):由 PROP_SEG(传播段) + PHASE_SEG1(相位段1) 组成,用于补偿传播延迟,并为采样点前的时间窗口做准备。
TSEG2 (时间段2):PHASE_SEG2,相位缓冲段,用于位采样之后的边沿相位调整。
TSEG1是采样点之前的时间段,主要补偿传播延迟。包含传播时间补偿(PROP_SEG),用于抵消总线传播延迟。决定采样点位置(采样通常在位时间的 75~87.5% 处)。
TSEG2是采样点之后的时间段,用于相位同步调整。用于相位缓冲,让接收器根据实际边沿调整定时,保持发收同步。必须 ≥ SJW(同步跳转宽度)。
一个位时间的总长度:
BitTime=(SYNC_SEG+TSEG1+TSEG2)×Tq
其中Tq = 1 / (fCANclk / BRP),时间量子由 CAN 时钟和预分频器 BRP 决定。
设:CAN 时钟 = 16 MHz
BRP = 2 → Tq = 1 / (16MHz/2) = 125 ns
SYNC_SEG = 1 Tq
TSEG1 = 13 Tq
TSEG2 = 2 Tq
则:BitTime=(1+13+2)×125ns=16×125ns=2μs
位速率 = 1 / 2µs = 500 kbps
采样点位置:Sampling=(1+13)/(1+13+2)=87.5%
也就是在一个位周期的 87.5% 处采样。
仲裁过程:
假设节点A、B和C的标识符分别为0x300(011 0000 0000),0x200(010 0000 0000),和0x100(001 0000 0000),仲裁过程如下:
- 第1位(最高位):
- 节点A发送0,节点B发送0,节点C发送0。总线电平为0(显性),所有节点继续仲裁。
- 第2位:
- 节点A发送1,节点B发送1,节点C发送0。总线电平为0(显性),节点A和节点B检测到总线电平与其发送的比特不匹配,因此节点A和节点B退出仲裁。
- 第3位:
- 节点C继续发送,因其他节点已退出,因此节点C成功仲裁。
MCU实现
CAN控制器的发送邮箱(Transmit Mailbox)和接收FIFO(Receive FIFO)是CAN外设内部用于缓冲报文的硬件资源,用来实现报文的排队、仲裁和缓存功能,以减少CPU对总线数据实时处理的压力。不同MCU的CAN控制器结构基本原理一致,但实现细节(邮箱数量、FIFO深度、触发机制等)有所不同。
发送邮箱 (Transmit Mailbox)存放待发送的CAN报文,每个邮箱包含:
报文ID(标准11位或扩展29位)
数据长度(DLC)
数据字段(最多8字节,CAN FD可到64字节)
发送控制标志(优先级、RTR等)
CAN控制器根据优先级(ID大小)和发送请求顺序,自动从邮箱中选取报文参与总线仲裁。
特点
多邮箱设计避免CPU等待总线空闲:CPU可提前写入多条报文,硬件自动排队发送。
某些MCU支持优先级调度,允许指定某邮箱优先于其他邮箱发送。
STM32经典CAN:3个发送邮箱
NXP S32K CAN-FD:32个发送缓冲区,可配置为邮箱模式或队列模式
TI TMS320系列:32个邮箱,可做收发混用
接收FIFO (Receive FIFO)存放接收到的CAN报文,CPU可以稍后再读取,避免因CPU处理慢而丢包。
FIFO通常带有:
报文过滤功能(ID过滤匹配才进入FIFO)
溢出标志(FIFO满时新数据被丢弃)
中断触发条件(至少1帧、FIFO半满、FIFO满等)
特点
提供缓冲深度,应对突发总线流量。
不同MCU支持多个独立FIFO,STM32支持2个接收FIFO(各深度3帧);NXP CAN-FD支持多个接收FIFO和多个独立过滤规则;高端MCU甚至支持DMA,将FIFO数据自动搬到内存。
浙公网安备 33010602011771号