一文搞懂 CAN 总线:从入门到 STM32 应用

一、什么是 CAN 总线?

CAN (Controller Area Network,控制器局域网总线)由 BOSCH 公司开发,是一种简洁、高速、易扩展且可靠性极高的串行通信总线。它广泛应用于汽车电子、工业控制、嵌入式设备等领域。

CAN 总线的核心特征:

  • 两线通信 :只需 CAN_H、CAN_L 两条线,布线简单。

  • 差分信号:抗干扰能力强,适合复杂的电磁环境。

  • 高速 CAN(ISO 11898):速率 125 k ~ 1 Mbps,距离 < 40 m。

  • 低速 CAN(ISO 11519):速率 10 k ~ 125 kbps,距离 < 1 km。

  • 异步通信:无需时钟线,节点间约定波特率即可。

  • 半双工多主结构:多个设备挂载在同一条总线上。

  • 报文 ID 仲裁:11 位(标准帧)或 29 位(扩展帧)ID,既区分功能,也决定总线优先级。

  • 可变数据长度:有效载荷 0 ~ 8 字节。

  • 广播 + 请求:支持主动发送数据帧,也支持通过遥控帧请求数据。

  • 内置可靠性机制:应答、CRC 校验、位填充、位同步、错误处理等。

二、CAN 与其他通信协议对比

| 协议 | 引脚 | 双工 | 时钟 | 电平 | 设备数量 | 典型场景 | | --- | --- | --- | --- | --- | --- | --- | | UART | TX、RX | 全双工 | 异步 | 单端 | 点对点 | 两个设备互连 | | I2C | SCL、SDA | 半双工 | 同步 | 单端 | 多设备 | 一主多从模块 | | SPI | SCK、MOSI、MISO、SS | 全双工 | 同步 | 单端 | 多设备 | 主控外挂高速模块 | | CAN | CAN_H、CAN_L | 半双工 | 异步 | 差分 | 多设备 | 多个控制器互相通信 |

CAN 最大的优势在于:多主、差分抗干扰、非破坏性仲裁、内置错误检测,这正是汽车网络所需要的。

三、硬件电路与物理层

3.1 总线拓扑

每个节点由 MCU + CAN 控制器 + CAN 收发器 组成。控制器输出 TX/RX,收发器将其转换为差分信号 CAN_H / CAN_L 后挂到总线上。

  • 高速 CAN :闭环网络,总线两端必须各接 120 Ω 终端电阻,用于阻抗匹配、抑制反射。

  • 低速 CAN :开环网络,在总线一端 接 2.2 kΩ 终端电阻。

  • 实际布线中,CAN_H 与 CAN_L 通常采用双绞线,进一步增强抗干扰能力。

3.2 电平标准:隐性 vs 显性

CAN 用两根线的电压差 表示数据位,而不是单线对地电压。

高速 CAN

| 逻辑 | 名称 | 电平差 V(CAN_H - CAN_L) | | --- | --- | --- | | 1 | 隐性(Recessive) | ≈ 0 V | | 0 | 显性(Dominant) | ≈ 2 V |

典型电压值:隐性时 CAN_H = CAN_L = 2.5 V;显性时 CAN_H ≈ 3.5 V、CAN_L ≈ 1.5 V。

低速 CAN

| 逻辑 | 电平差 | | --- | --- | | 1(隐性) | ≈ -1.5 V | | 0(显性) | ≈ 3 V |

关键特性:"线与"。只要任意一个节点发送显性(0),总线就呈现显性;只有当所有节点都发隐性(1)时,总线才为隐性。这一特性是 CAN 总线仲裁的基础。

3.3 CAN 收发器

常用高速 CAN 收发器如 TJA1050 、PCA82C250 、TJA1042 等。它负责:

  • 将控制器来的 TX 单端信号转成差分电平发到总线;

  • 将总线差分电平转回 RX 单端信号给控制器。

四、CAN 帧格式

4.1 五种帧类型

| 帧类型 | 用途 | | --- | --- | | 数据帧 | 节点主动发送数据(广播式) | | 遥控帧 | 节点主动请求数据(请求式) | | 错误帧 | 检测到错误时,通知其他节点并终止当前发送 | | 过载帧 | 接收方来不及处理,要求发送方暂缓 | | 帧间隔 | 分隔数据帧/遥控帧与后续帧 |

4.2 数据帧结构(标准帧 11 位 ID)

| 字段 | 长度 | 说明 | | --- | --- | --- | | SOF | 1 bit | 帧起始,显性位,标志数据开始 | | ID | 11 bit | 标识符,区分消息功能,ID 越小优先级越高 | | RTR | 1 bit | 远程请求位;数据帧为 0,遥控帧为 1 | | IDE | 1 bit | 扩展标志;0 = 标准帧,1 = 扩展帧 | | r0 | 1 bit | 保留位 | | DLC | 4 bit | 数据长度码,0 ~ 8 | | Data | 0 ~ 8 B | 实际传输的数据 | | CRC | 15 bit | 循环冗余校验 | | CRC 界 | 1 bit | CRC 结束标志 | | ACK | 1 bit | 应答位,接收方正确接收后拉低 | | ACK 界 | 1 bit | ACK 结束标志 | | EOF | 7 bit | 帧结束,7 个隐性位 |

扩展帧 :CAN 2.0B 中将 ID 扩展到 29 位,增加了 SRR 位(替代 RTR,固定为 1),并在标准帧的 r1 位置引入了 IDE 位。当标准帧 11 位 ID 与扩展帧的高 11 位 ID 相同时,标准帧优先级更高,这是通过 SRR = 1(隐性)来保证的。

4.3 遥控帧

遥控帧与数据帧结构几乎相同,但:

  • RTR = 1(隐性);

  • 没有数据段;

  • 用于请求总线上其他节点发送对应 ID 的数据。

4.4 位填充(Bit Stuffing)

发送方每发送 5 个相同电平 后,会自动插入一个相反电平的填充位;接收方检测到填充位后自动移除。

作用:

  1. 提供额外的跳变沿,帮助接收方执行再同步;

  2. 防止长序列无跳变导致采样失准;

  3. 把正常数据流与错误帧、过载帧区分开;

  4. 保持总线在发送正常数据时的活跃状态。

五、位时序、采样与波特率

CAN 没有时钟线,所有节点靠约定波特率工作。每个节点都按自己的时钟对总线采样。

5.1 位时序分段

一个数据位被细分为若干最小时间单位 Tq(Time Quantum),并进一步划分为:

| 段 | 长度 | 作用 | | --- | --- | --- | | SS (同步段) | 1 Tq | 期望出现跳变沿,用于同步 | | PTS (传播段) | 1 ~ 8 Tq | 补偿信号在总线上的传播延迟 | | PBS1 (相位缓冲段 1) | 1 ~ 8 Tq | 必要时延长以再同步 | | PBS2(相位缓冲段 2) | 2 ~ 8 Tq | 必要时缩短以再同步 |

采样点 通常位于 PBS1 末尾 / PBS2 起始处,即一位的中心附近。

5.2 同步机制

  • 硬同步:在每一帧的 SOF 下降沿,所有接收方将自己的位时序拨到 SS 段位置。硬同步只在 SOF 处有效一次。

  • 再同步 :如果后续数据位跳变沿偏离了 SS 段,接收方通过 SJW (再同步补偿宽度,1 ~ 4 Tq)延长 PBS1 或 缩短 PBS2,把采样点重新拉回中心。

5.3 波特率计算

bash 复制代码
波特率 = 1 / 一个数据位的时长
      = 1 / (T_SS + T_PTS + T_PBS1 + T_PBS2)

例如:SS = 1 Tq,PTS = 3 Tq,PBS1 = 3 Tq,PBS2 = 3 Tq,Tq = 0.5 μs,则:

bash 复制代码
一个位 = (1+3+3+3) × 0.5 μs = 4 μs
波特率 = 1 / 4 μs = 200 kbps

在 STM32 中,位时序用 BS1、BS2 表示:

bash 复制代码
波特率 = APB1 / (BRP + 1) / (1 + (TS1 + 1) + (TS2 + 1))

其中 SS = 1 Tq 固定,BS1 = TS1 + 1,BS2 = TS2 + 1。

六、总线仲裁

6.1 规则一:先占先得

如果当前已有设备在发送数据帧/遥控帧,其他设备不能同时发送数据帧/遥控帧(但可以发送错误帧/过载帧破坏当前帧)。只有当总线出现连续 11 个隐性位时,才认为总线空闲,设备才能开始发送。

6.2 规则二:非破坏性仲裁

若多个设备同时开始发送,CAN 根据 ID 逐位比较 进行仲裁。ID 越小,优先级越高。

实现仲裁依赖两个机制:

  1. 线与特性:任何节点发显性(0),总线就为 0;只有全发隐性(1)时总线才为 1。

  2. 回读机制:每个节点发完一位后都会读回总线电平。如果发的是 1,读回却是 0,说明优先级更高的节点发了 0,该节点自动退出竞争,转为接收。

因为仲裁不会破坏已经发出的数据,所以称为非破坏性仲裁。

6.3 优先级补充规则

  • 同 ID 时:数据帧优先级高于遥控帧(RTR = 0 vs 1)。

  • 标准帧 vs 扩展帧 :当标准帧 11 位 ID 与扩展帧高 11 位 ID 相同时,标准帧优先级更高(由 SRR = 1 保证)。

七、错误处理

7.1 五种错误类型

| 错误类型 | 说明 | | --- | --- | | 位错误 | 发送方读回的总线电平与发送的不一致(仲裁期间除外) | | 填充错误 | 违反位填充规则(连续 6 个相同位) | | CRC 错误 | 接收方 CRC 计算结果与发送方不一致 | | 格式错误 | 固定格式位(如帧间隔、ACK 界等)不符合规定 | | ACK 错误 | 发送方在 ACK 位未收到显性应答 |

7.2 三种错误状态

每个节点通过两个计数器 TEC (Transmit Error Counter)和 REC(Receive Error Counter)管理自身状态:

| 状态 | 条件 | 行为 | | --- | --- | --- | | 主动错误 | TEC < 128 且 REC < 128 | 正常通信,检测到错误时发送主动错误帧(6 个显性位) | | 被动错误 | TEC ≥ 128 或 REC ≥ 128 | 仍可通信,但只能发送被动错误帧(6 个隐性位) | | 总线关闭 | TEC > 255 | 退出总线通信,需恢复过程 |

7.3 离线恢复

STM32 中 ABOM 位控制离线恢复:

  • ABOM = 1:进入总线关闭后自动进入恢复过程;

  • ABOM = 0:软件需先请求进入再退出初始化模式,才会开始恢复。

八、STM32 bxCAN 外设应用

8.1 资源概览

STM32 内置 bxCAN 控制器,支持 CAN 2.0A/B,最高 1 Mbps。典型资源(以 STM32F103C8T6 为例):

  • 3 个发送邮箱(带可配置优先级);

  • 2 个接收 FIFO,每个 3 级深度;

  • 14 个过滤器组(互联型为 28 个);

  • 支持时间触发通信、自动离线恢复、自动唤醒、禁止自动重传、双 CAN 模式等。

8.2 发送与接收流程

发送流程:选择一个空邮箱 → 写入报文 → 请求发送。

接收流程:接收到报文 → 经过过滤器匹配 → 进入 FIFO 0 或 FIFO 1 → CPU 读取。

8.3 关键配置位

| 位 | 置 1 | 置 0 | | --- | --- | --- | | NART | 禁止自动重传,只发一次 | 发送失败自动重传直到成功 | | TXFP | 发送优先级按请求顺序 | 发送优先级按 ID 大小 | | RFLM | FIFO 溢出时丢弃新报文 | FIFO 溢出时覆盖最后一条 |

8.4 标识符过滤器

每个过滤器由两个 32 位寄存器 R1[31:0]、R2[31:0] 组成,可配置为:

  • FSCx(位宽):0 = 16 位,1 = 32 位;

  • FBMx(模式):0 = 屏蔽模式(Mask),1 = 列表模式(List);

  • FFAx(关联):0 = 关联 FIFO 0,1 = 关联 FIFO 1;

  • FACTx(激活):0 = 禁用,1 = 启用。

列表模式 :精确匹配若干 ID。 屏蔽模式 :用 ID + Mask 匹配一段 ID 范围。

注意:ID 写入寄存器时通常需要左移(标准 ID 左移 21,扩展 ID 左移 3 等),具体规则需参考 STM32 参考手册。

8.5 测试模式

| 模式 | 作用 | | --- | --- | | 静默模式 | 监听总线,不影响总线,用于分析 | | 环回模式 | 自测试,发送的报文可从 TX 引脚检测到 | | 环回静默模式 | 热自测试,不影响总线 |

8.6 工作模式

  • 初始化模式:配置 CAN 外设,禁止收发;

  • 正常模式:配置完成后进入,正常收发;

  • 睡眠模式 :低功耗,AWUM = 1 时检测到总线活动自动唤醒,AWUM = 0 需软件唤醒。

8.7 中断

bxCAN 占用 4 个中断向量:

  1. 发送中断:发送邮箱空;

  2. FIFO 0 中断:收到报文 / FIFO 满 / FIFO 溢出;

  3. FIFO 1 中断:收到报文 / FIFO 满 / FIFO 溢出;

  4. 状态/错误/唤醒/睡眠中断。

8.8 时间触发通信(TTCM)

使能 TTCM 后,bxCAN 内置一个 16 位计数器,每个 CAN 位时间自增一次。发送帧 SOF 时捕获计数值到发送邮箱的 TIME 寄存器;接收帧 SOF 时捕获到接收 FIFO 的 TIME 寄存器。若使能 TGT 且 DLC = 8,时间戳还会被写入数据段最后两个字节。

九、小结

| 知识点 | 一句话总结 | | --- | --- | | 物理层 | 两线差分,显性 0 / 隐性 1,终端电阻匹配 | | 帧格式 | 标准 11 位 ID / 扩展 29 位 ID,数据帧含 0~8 B 数据 | | 位时序 | SS + PTS + PBS1 + PBS2,采样点对齐中心 | | 仲裁 | ID 越小优先级越高,显性覆盖隐性,非破坏性 | | 错误处理 | 5 种错误、3 种状态、TEC/REC 计数器 | | STM32 | bxCAN 自动收发、过滤器、FIFO、中断、时间戳 |

CAN 总线之所以能成为汽车电子的事实标准,核心在于它在物理层、数据链路层、错误处理层都做了完整而简洁的设计。理解了"差分电平、非破坏性仲裁、位时序、错误状态机"这几个关键点,再看任何车载网络或 STM32 CAN 代码都会事半功倍。

十、补充AutoSAR架构下的CAN通信


相关推荐
lightning_bug1 小时前
Windows系统Docker+SpringBoot+H5+Mysql+Redis打包部署流程
后端·架构
码事漫谈1 小时前
国庆七天,AI圈没一天消停
后端
掘金酱2 小时前
[稀土掘金 × 火山引擎] AI用量周榜冲刺赛|获奖名单公示
前端·人工智能·后端
montEvergreen2 小时前
RTMP 里的那根“连接线”:读一份 NetConnection 源码
后端·go
montEvergreen2 小时前
RTMP 握手:一场客户端与服务端的“暗号”对决
后端·go
qianmoq2 小时前
GrantForge 开源:基于 Spring Boot 构建统一权限平台,让权限管理不再从零开始
后端
泡泡oO2 小时前
“如果你还在用Superpowers,那我不要和你说话”
前端·后端·全栈
YatHinLay2 小时前
FastThreadLocal
后端
newerp2 小时前
sync.Mutex 源码深度拆解:正常模式(自旋)与饥饿模式
后端·程序员·go