CAN控制器基础理论
181.1.4 CAN控制器基础理论
本课展示的是 STM32CubeMX 建立工程、配置 CAN/USART1 并生成默认工程的过程,结尾明确说业务代码下节课再写;因此这里不把 CubeMX 自动生成的库代码或后续课程源码提前抄入第二行。配套
.ioc仅用于核对本课实际配置。
一、看控制器基础理论
这一课从 STM32F103ZET6 内部的 bxCAN 控制器入手,先认识发送邮箱、接收过滤器和接收 FIFO,再在 STM32CubeMX 中建立工程并计算 500 kbit/s 位时序。
先把完整数据路径放在一起:
应用程序
│ ID、DLC、数据
▼
STM32F103ZE 内部 bxCAN 控制器
│ CANTX CANRX ▲
▼ │
外部 CAN 收发器:逻辑电平 ↔ CANH/CANL 差分电平
│
└──────────── CAN 总线及其他节点 ────────────
bxCAN 是控制器,负责组帧、仲裁、过滤、CRC、ACK、错误管理和缓冲;外部收发器负责电气层转换。即使 MCU 内置 bxCAN,也不能把 PA11/PA12 直接接到 CANH/CANL。
1.1 bxCAN
1.1.1 bxCAN的特点
bxCAN 是 Basic Extended CAN 的缩写。STM32F103ZE 上的 bxCAN 支持 CAN 2.0A/2.0B Active,也就是支持 11 位标准标识符和 29 位扩展标识符的 Classical CAN,标称位率最高 1 Mbit/s;它不支持 CAN FD。
与本课最相关的硬件资源如下:
| 资源 | STM32F103ZE 中的情况 | 用途 |
|---|---|---|
| 发送邮箱 | 3 个 | 软件可预先放入最多 3 个待发报文,硬件调度其中一帧发送 |
| 接收 FIFO | 2 个,每个深度为 3 帧 | 暂存已经通过过滤器的完整报文,给软件留下处理时间 |
| 过滤器组 | 14 组 | 按标识符等字段决定接收或丢弃报文,并把通过的报文分配给 FIFO0 或 FIFO1 |
| 工作模式 | 初始化、正常、睡眠 | 分别用于配置、参与总线通信和低功耗 |
| 测试模式 | 静默、环回、静默环回 | 用于监听或自测;正常双节点通信不能误用静默模式 |
原笔记中的“未同步、未填充、仲裁时间处罚、通信和测试模式”是语音识别拼接错误,不是一组规范的 bxCAN 模式名称。无破坏仲裁、位填充、自动错误检测等是 CAN 协议机制,不应与控制器工作模式混成一项。
这些功能降低了 CPU 对每一位总线时序的干预,但不等于“打开 CAN 外设就能通信”。软件仍须正确配置时钟、位时序、模式、过滤器和 GPIO,并启动控制器;硬件侧还必须有收发器、正确的 CANH/CANL 接线与终端电阻。
1.1.2 bxCAN的框图
课程手册中的“双 CAN 框图”覆盖了带 CAN1、CAN2 的互联型器件,因此下半部分会出现“从 bxCAN”。本课使用的 STM32F103ZET6 只有 1 个 CAN 控制器,阅读时只需沿上半部分的 CAN1 主控制器理解:
┌─ 发送邮箱0
CPU/寄存器 ↔ bxCAN ──┼─ 发送邮箱1 ─→ 发送调度器 ─→ CAN 内核 ─→ CANTX
└─ 发送邮箱2
CANRX ─→ CAN 内核 ─→ 接收过滤器 ─┬─→ FIFO0(3 帧深度)─→ CPU
└─→ FIFO1(3 帧深度)─→ CPU
框图中的“邮箱 0、1、2”有两类含义:
- 发送侧确实有 3 个彼此独立的发送邮箱,每个邮箱保存 1 个完整待发报文;它们不是一个长度为 3 的普通 C 数组。
- 接收侧的 FIFO0、FIFO1 各有 3 级存储深度,可各暂存 3 个完整报文;软件只能先访问队首,也就是最早进入该 FIFO 的报文。
发送调度器决定三个待发邮箱中哪一个先上总线。默认可按报文标识符优先级调度;设置 TXFP 后也可按发送请求先后调度。无论内部怎样排队,真正上总线时仍必须参加 CAN 的逐位仲裁。
1.1.3 bxCAN的过滤器
这里应使用 过滤器组(filter bank) 这一准确名称,不能简单理解成“有 14 个槽,所以只能接收 14 个 ID”。每个过滤器组由两个 32 位寄存器组成,还能选择:
- **32 位或 16 位宽度:**决定用完整 32 位比较项,还是把寄存器拆成更多 16 位比较项;
- **标识符列表模式:**收到的标识符等相关位必须与列表项相等;
- **标识符屏蔽模式:**通过掩码指定哪些位必须匹配、哪些位不关心;
- **FIFO 分配:**匹配该组的报文进入 FIFO0 还是 FIFO1;
- **启用状态:**不用的过滤器组应保持关闭。
STM32F103ZE 属于 STM32F103xx 高容量产品,只有一个 bxCAN,提供 14 个过滤器组,编号 0~13。课程手册所说的“互联型产品”特指 STM32F105xx/STM32F107xx:其 CAN1、CAN2 共享 28 个过滤器组。视频举出的 F407 属于 STM32F4 系列,不能因为它带以太网 MAC 就套用 RM0008 中“互联型产品”的分类;F407 的资源应查它自己的数据手册和 RM0090。
过滤器组的数量、位宽和模式共同决定能匹配多少个 ID,所以“14 个过滤器组”不等于“只能精确接收 14 种报文”。后续配置 HAL 过滤器结构体时,还会具体学习 ID 在 32 位/16 位过滤寄存器中的对齐方式。
1.1.4 bxCAN的框图分析
CAN 使用广播:一帧会到达总线上的所有节点,标识符表达消息内容和仲裁优先级,并不是天然的目标设备地址。接收过滤器让每个节点只把自己关心的报文交给软件。
一帧的接收路径是:
CANH/CANL
↓ 外部收发器判决显性/隐性
CANRX
↓ bxCAN 完成协议接收和帧级检错
过滤器比较 ID、IDE、RTR 等位
├─ 不匹配:硬件丢弃,不进入接收 FIFO
└─ 匹配:按过滤器配置进入 FIFO0 或 FIFO1
↓
软件读取并释放队首报文
过滤器主要比较标识符及 IDE、RTR 等控制位,不会按 0~8 字节数据负载的内容进行通用匹配。应用如果需要根据温度值、命令参数等数据内容再筛选,必须在报文进入 FIFO 后由软件完成。
过滤发生在 CAN 控制器已经正确接收协议帧之后。它能减少无关报文占用 FIFO 和 CPU,却不会减少这些报文在物理总线上的带宽占用,也不表示被过滤掉的帧在总线上不存在。
1.2 邮箱与接收FIFO
1.2.1 邮箱与接收FIFO的概念
发送邮箱、过滤器和接收 FIFO 的共同目标是让协议实时性与软件处理速度解耦:
| 部件 | 数据方向 | 解决的问题 |
|---|---|---|
| 发送邮箱 | 软件 → CAN 控制器 | 软件先写入待发帧,不必逐位驱动总线;控制器等待合适时机发送 |
| 接收过滤器 | 总线 → 控制器内部 | 在进入 FIFO 前丢弃软件不关心的 ID,减少 CPU 负担 |
| 接收 FIFO | 控制器 → 软件 | 临时保存突发到达的报文,让 CPU 不必在 EOF 后立刻完成全部业务处理 |
视频把这些硬件归因于“CAN 数据太快、软件处理不过来”,这是便于入门的说法,但不够完整。bxCAN 的复杂性还来自共享总线、多主仲裁、自动重发、错误状态和按标识符过滤。UART 控制器也可能带 FIFO 和 DMA,不能概括成“串口一定只有一个收发寄存器,也不需要硬件缓冲”。
1.2.2 接收FIFO
FIFO 是硬件缓冲,不是无限容量。STM32F103ZE 有 FIFO0、FIFO1 两个接收 FIFO,每个只能保存 3 个完整 CAN 报文。过滤器会把匹配的报文路由到指定 FIFO;软件应及时查询或响应中断,读取队首报文并释放输出邮箱,之后才能依次访问下一帧。
若一个 FIFO 已有 3 帧而软件仍未释放,新报文再到来就会产生溢出:
- 未启用 FIFO 锁定时,硬件保留更新的报文,队列中最后收到的旧报文可能被新报文覆盖;
- 启用 FIFO 锁定时,已有 3 帧保持不变,新到报文被丢弃;
- 两种策略都会丢数据,只是决定“丢旧的还是丢新的”。
因此过滤器和 3 级 FIFO 只能吸收短暂的处理延迟,不能代替及时读取、接收中断、合理的任务优先级或上层流量控制。若总线持续产生报文的平均速率高于软件消费速率,FIFO 最终仍会溢出。
1.2.3 先进先出
FIFO 是 First In, First Out,即“先进先出”。可把它想成排队窗口:
新报文进入 → [第3帧] [第2帧] [第1帧] → 软件先读取第1帧
“先进入的先被读出”保证同一 FIFO 内的报文顺序。软件读取队首后还要释放该邮箱,硬件才会让下一帧成为新的队首。HAL 驱动的接收接口会把报文头和数据读出并完成相应释放操作,但调用者仍需检查是否有待处理报文及返回状态。
发送侧不要误称为“一个能保存 3 帧的大 FIFO”。它是 3 个独立发送邮箱,硬件依据配置的调度规则选择其中一帧;软件写满 3 个邮箱后,必须等至少一个邮箱发送完成或被中止,才能再装入新报文。
1.2.4 写代码
这一标题沿用原笔记,但视频本节实际只完成 建工程、配置外设、生成并编译默认工程,没有开始编写 CAN 收发业务代码。课程结尾明确把具体代码留到下一课,因此不应提前收录配套目录中后来追加的过滤、发送或接收代码。
视频中的工程建立步骤可整理为:
- 在磁盘中新建专题代码目录
unit3code。尽量使用英文、数字和半角下划线,避免旧版 Keil、构建脚本或第三方工具对中文路径兼容不良;“中文路径一定导致卡顿”不是所有版本都必然发生的结论。 - 在 STM32CubeMX 选择
Start My project from MCU,按实际芯片选择STM32F103ZET6,封装为 LQFP144。 - 在 RCC 中把 HSE 设置为外部晶体/陶瓷谐振器,在 SYS 中把 Debug 设置为
Serial Wire,保留 PA13/SWDIO、PA14/SWCLK 供 ST-Link 下载调试。 - 把系统时钟配置为 72 MHz:课程板使用 8 MHz HSE,经 PLL ×9 得到 72 MHz;APB1 再二分频为 36 MHz。
- 启用 CAN1,默认引脚为 PA11/CAN_RX、PA12/CAN_TX;位时序设置为 Prescaler=
4、BS1=9 TQ、BS2=8 TQ,CubeMX 显示 500 kbit/s。 - 启用 USART1 异步模式,配套
.ioc显示 PA9/USART1_TX、PA10/USART1_RX,供后续打印调试。 - Project Manager 中工程名为
01Can_Test,工具链选择MDK-ARM;Code Generator 勾选为每个外设生成配套.c/.h文件,然后生成工程。 - 在生成目录的
MDK-ARM下打开 Keil 工程并编译。此时编译通过只说明 CubeMX 骨架和初始化代码能构建,不等于 CAN 总线已经完成收发验证。
配套 01Can_Test.ioc 与视频一致地记录了 STM32F103ZET6、CAN1、USART1、72 MHz 系统时钟、36 MHz APB1、Prescaler=4、BS1=9 TQ、BS2=8 TQ 和计算结果 500000 bit/s。
1.3 存储器和总线构架
查 MCU 的总线框图可知,STM32F103ZE 的 CAN1 挂在 APB1。本工程时钟链如下:
外部晶振 HSE 8 MHz
│ PLL ×9
▼
SYSCLK 72 MHz
│ AHB ÷1
▼
HCLK 72 MHz
│ APB1 ÷2
▼
PCLK1 36 MHz ──→ bxCAN 位时序逻辑
这里要区分 CPU 主频、APB1 外设时钟与时间份额时钟:
- CPU/HCLK 为 72 MHz;
- APB1 外设时钟 PCLK1 为 36 MHz;
- CAN Prescaler 设置为 4 后,时间份额时钟为
36 MHz ÷ 4 = 9 MHz; - 9 MHz 不是最终 CAN 位率,因为一个 CAN 位还包含多个 TQ。
STM32 定时器在 APB 预分频不为 1 时常会得到 2 倍 PCLK 的定时器时钟,但 CAN 不是 APB1 定时器,不能套用该倍频规则;本工程 CAN 位时序公式使用 PCLK1=36 MHz。
课程旧版中文手册还提醒:在中容量和大容量 STM32F103 器件中,USB 与 CAN 共享专用 SRAM,二者不能在同一时刻访问该存储区。PA11/PA12 也正好是 USB D-/D+ 与默认 CAN_RX/CAN_TX 的复用引脚,所以本项目选择 CAN 后,不能同时把同一引脚用于 USB 数据通信。
1.4 CAN控制器的位时序
CAN 没有随数据一起传送的独立时钟线。每个节点依靠本地时钟产生名义位时间,再通过帧起始边沿同步,并利用后续边沿重新同步。位时序配置决定:一个位持续多久、在哪个时刻采样,以及发生相位偏差时最多调整多少。
1.4.1 二进制报文
CAN 在线路上同样传输显性 0 与隐性 1,但控制器不会把一个位仅当作不可再分的时间块。CAN 标准从概念上把一个名义位划分为:
SYNC_SEG | PROP_SEG | PHASE_SEG1 | PHASE_SEG2
SYNC_SEG:同步段,期望总线跳变出现在这里,固定为 1 TQ;PROP_SEG:补偿收发器与总线往返传播延迟;PHASE_SEG1、PHASE_SEG2:通过重新同步进行延长或缩短,以补偿节点时钟和边沿相位偏差;- 采样点位于
PHASE_SEG1与PHASE_SEG2之间。
STM32 bxCAN 没有让软件分别填写四段,而是把 PROP_SEG + PHASE_SEG1 合并为 BS1,把 PHASE_SEG2 表示为 BS2,所以寄存器/CubeMX 视角只有三段:
SYNC_SEG(1 TQ) | BS1(1~16 TQ) | BS2(1~8 TQ)
原笔记写“相位缓冲段 2 为 2~8 TQ”不符合 STM32F103 bxCAN 的可编程范围;RM0008 明确给出 BS2 为 1~8 TQ。重新同步跳转宽度 SJW 可配置为 1~4 TQ。
1.4.2 数据位
一个 CAN 数据位的总时长为:
[ t_{bit}=t_{SYNC}+t_{BS1}+t_{BS2}=(1+BS1+BS2)\times t_q ]
采样点位于 BS1 结束、BS2 开始的位置,因此采样点占位百分比为:
[ Sample\ Point=\frac{1+BS1}{1+BS1+BS2}\times100% ]
划分这些段不是因为 CAN 的 0、1 比 UART “更复杂”,而是为了在没有独立时钟线的共享总线上确定同步和采样位置,并允许控制器依据边沿做有限度的重新同步。
视频所说“传播速度太快会采错”表述不准确。真正的问题是信号传播速度有限:线缆越长、位率越高,线缆传播延迟、收发器延迟和节点时钟误差相对于一个位时间所占比例越大。合理的 BS1、BS2、SJW 和采样点能留出裕量,但不能无条件保证数据“一定采对”,还要结合总线长度、拓扑、收发器、终端和晶振误差设计。
1.4.3 时间份额
TQ 的全称是 Time Quantum(时间量子/时间份额),不是转录中的 Time Quater。它是组成一个 CAN 位的最小时间单位,不等于一个完整数据位。
bxCAN 的 TQ 由 APB1 外设时钟和波特率预分频器决定:
[ t_q=\frac{Prescaler}{f_{PCLK1}} ]
本工程 fPCLK1=36 MHz、Prescaler=4:
[ f_{TQ}=\frac{36\ MHz}{4}=9\ MHz ]
[ t_q=\frac{1}{9\ MHz}\approx111.11\ ns ]
如果只把 Prescaler 改为 16,则:
[ t_q=\frac{16}{36\ MHz}\approx444.44\ ns ]
但这也会改变最终位率,不能把 Prescaler 当成只影响显示、不影响通信的参数。另需注意:CubeMX/HAL 中写 Prescaler=4,底层 CAN_BTR 寄存器的 BRP 域编码为 4-1=3;这是寄存器采用“实际值减 1”编码,不是配置矛盾。
1.4.4 tbs 1和tbs 2
本标题沿用原笔记,准确的段名是 BS1 和 BS2;公式中的 tBS1、tBS2 才表示相应时间长度。
BS1 = PROP_SEG + PHASE_SEG1,可配置 1~16 TQ,它的末端确定采样点;BS2 = PHASE_SEG2,可配置 1~8 TQ,位结束后进入下一位;SJW限制每次重新同步时 BS1 最多延长或 BS2 最多缩短多少 TQ,本工程保持 CubeMX 默认的 1 TQ。
名义位率公式为:
[ BitRate=\frac{f_{PCLK1}}{Prescaler\times(1+BS1+BS2)} ]
这里额外的 1 就是固定的同步段 SYNC_SEG。在二进制 CAN 中,一个符号只承载一个位,所以日常所说的“500 k 波特”与 500 kbit/s 数值相同;写笔记时用 kbit/s 更能直接表达 CAN 位率。
1.4.5 tq值计算
把视频设置代入公式:
PCLK1 = 36 MHz
Prescaler = 4
SYNC_SEG = 1 TQ
BS1 = 9 TQ
BS2 = 8 TQ
总 TQ 数 = 1 + 9 + 8 = 18 TQ
单个 TQ:
[ t_q=\frac{4}{36\ MHz}=111.11\ ns ]
单个位时间:
[ t_{bit}=18\times111.11\ ns\approx2\ \mu s ]
最终位率:
[ BitRate=\frac{1}{2\ \mu s}=500,000\ bit/s=500\ kbit/s ]
所以视频中 Prescaler=4、BS1=9 TQ、BS2=8 TQ 得到 500 kbit/s 的计算是正确的。原笔记末尾乱码公式应还原为:
[ 1\ TQ=\frac{2\ \mu s}{18}\approx111.11\ ns ]
还必须检查采样点:
[ Sample\ Point=\frac{1+9}{18}\times100%\approx55.56% ]
这说明“位率正确”不等于“位时序已经最优”。55.56% 是本课演示配置产生的较早采样点;真实项目还应结合线长、节点数、收发器延迟、晶振误差和目标网络要求选择更合适的 BS1、BS2 与 SJW。通信双方至少必须使用相同的标称位率,实际工程也通常统一位时序参数,避免采样裕量不足。
最后,本课还启用了 USART1 用于后续调试,并生成了 Keil 工程;到此只完成外设与工程骨架。CAN 过滤器初始化、启动控制器、装填发送邮箱和读取接收 FIFO 都属于后续课程代码,不能在本课提前补全。
参考资料
- 课程配套 STM32中文参考手册:核对旧版第 22 章中的 bxCAN 特点、双 CAN 框图、发送邮箱、接收 FIFO、过滤器组和位时序图。
- 课程配套 01Can_Test.ioc:核对 MCU 型号、PA11/PA12、PA9/PA10、72 MHz/36 MHz 时钟以及 Prescaler=
4、BS1=9 TQ、BS2=8 TQ的实际配置。 - ST 官方 RM0008 Rev 21:核对当前版 bxCAN 的邮箱、过滤器、FIFO、工作模式、位时序范围和计算公式;新版中 bxCAN 位于第 24 章。
- ST 官方 STM32F103 系列资料页:核对 STM32F103 高容量产品的数据手册、参考手册与勘误表入口。