【双 MCU 架构车载仪表终端(CAN 互联)】STM32H7 FDCAN 外设
1. 引言
STM32H7 内置了 FDCAN 外设(CAN with Flexible Data Rate 灵活数据速率控制器局域网络),支持 CAN 协议规范第 2.0 版 A、B 部分和 ISO 11898-1:2015,以及 CAN FD 协议规范第 1.0 版。
2. FDCAN 外设简介
| 参数 / 特性 | 说明 / 细节 |
|---|---|
| 协议标准 | 符合 CAN 协议第 2.0 版 A、B 部分和 ISO 11898-1:2015,以及 CAN FD 协议规范第 1.0 版 |
| CAN FD 数据长度 | 最多支持收发 64 个数据字节 |
| TTCAN 协议支持 | 硬件完全支持 TTCAN 协议级别 1 和级别 2(仅限 FDCAN1) |
| 时间触发通信 | 支持事件同步时间触发通信(仅限 FDCAN1) |
| 错误记录 | CAN 错误记录 |
| 软件支持 | 支持 AUTOSAR 和 J1939 |
| 接收过滤 | 改进了接收过滤 |
| 接收 FIFO | 两个可配置接收 FIFO |
| 优先级指示 | 接收到高优先级消息时单独发出信号指示 |
| 专用接收缓冲区 | 多达 64 个专用接收缓冲区 |
| 专用发送缓冲区 | 多达 32 个专用发送缓冲区 |
| 发送 FIFO/队列 | 可配置发送 FIFO/队列 |
| 发送事件 FIFO | 可配置发送事件 FIFO |
| 消息 RAM 共享 | FDCAN1 和 FDCAN2 两个模块共用同一消息 10KB RAM |
| 测试模式 | 可编程环回测试模式 |
| 中断控制 | 可屏蔽模块中断 |
| 时钟域 | 两个时钟域:APB 总线接口和 CAN 内核时钟 |
| 电源管理 | 支持掉电 |
STM32H7 两个 CAN 模块(FDCAN1 和 FDCAN2)共用那 10KB 报文 RAM,均支持CAN 协议规范第 2.0 版 A、B 部分和 CAN FD 协议规范第 1.0 版。
此外,第一个 CAN 模块 FDCAN1 支持 ISO 11898-4 中规定的时间触发 CAN (TTCAN),包 括事件同步时间触发通信、全局系统时间和时钟漂移补偿。
2.1 与 bxCAN 对比
| 特性 | bxCAN(F103) | FDCAN(H757) |
|---|---|---|
| 仲裁段 / 数据段速率 | 最高 1Mbps,每帧只有一种速率 | 1Mbps / 8Mbps |
| 每帧数据长度 | 0~8 字节 | 0~64 字节 |
| 报文存储 | 512 字节,结构固定 | 10KB,按需划分,CPU 可访问 |
| 发送 | 3 个邮箱,整体作 FIFO 或按 ID 优先 | 专用缓冲 + FIFO/队列,最多 32 元素 |
| 接收 | 2 个 FIFO × 3 级(共 6 帧) | 2 个 FIFO × 64 + 64 专用缓冲,最多 192 元素 |
| FIFO 满时的覆盖 | 不锁定模式:覆盖最新存入的那帧 | 覆盖模式:覆盖最旧的元素 |
| 过滤器 | 14 组(互联型 28),四种模式组合 | 标准 128 + 扩展 64 元素,新增范围、拒绝、接受非匹配 |
| 其他 | — | 受限操作模式、发送暂停、收发器延迟补偿、时钟校准单元 |
3. CAN 框图

双中断线:
FDCAN 外设提供 fdcan_intr0_it 和 fdcan_intr1_it 两条中断线。通过对 FDCAN_ILE 寄存器 中的 EINT0 和 EINT1 位进行编程,可分别使能或禁止这两条中断线。
CAN 内核:
CAN 内核包含协议控制器和接收/发送移位寄存器。它可处理所有 ISO 11898-1: 2015 协议 功能,并支持 11 位和 29 位标识符。
同步:
同步模块将来自 APB 时钟域的信号同步到 CAN 内核时钟域,以及将来自 CAN 时钟域的信 号同步到 APB 时钟域。
消息 RAM 接口:
通过 RAM 控制器/仲裁器将 FDCAN 访问连接到外部 10 KB 消息 RAM。
3.1 发送处理单元
该处理单元控制从消息 RAM 到 CAN 内核的消息传输。最多可配置 32 个发送缓冲区进行发送。发送缓冲区可用作专用发送缓冲区、发送 FIFO(发送队列的组成部分)或二者的组合。发送事件 FIFO 会将发送时间戳与相应的消息 ID 存储在一起,另外还支持取消发送。
在 FDCAN1 上,发送处理单元还会实现帧同步实体 (FSE),按照 ISO11898-4 的规定控制时间触发通信。它会将自身与 CAN 总线上的参考消息进行同步,控制周期时间和全局时间, 并根据预先定义的消息调度(系统矩阵)处理发送操作。它还会处理与消息 RAM 中的消息 相关联的系统矩阵的时间标记。停止监视触发、事件触发和时间标记中断均为同步接口。
3.2 接收处理单元
该处理单元控制着从 CAN 内核接收的消息到外部消息 RAM 的传输。接收处理单元支持两个 接收 FIFO(每个 FIFO 的大小均可配置)以及最多 64 个专用接收缓冲区(用于存储所有通 过验收过滤的消息)。专用接收缓冲区仅用于存储具有特定标识符的消息,与接收 FIFO 有 所不同。每条消息均与其接收时间戳存储在一起。对于 11 位 ID,最多可定义 128 个过滤器; 对于 29 位 ID,最多可定义 64 个过滤器。
4.FDCAN 的核心设计
4.1 报文缓冲结构 RAM 化
由于中文版手册有极大的翻译错误,这里放英文版手册的截图上来。

bxCAN 的缓冲结构是焊死的:3 个发送邮箱、2×3 级接收 FIFO。而 FDCAN 改为直接使用一段 10KB 的 RAM,这一段 RAM 中划分成若干个区域,其中每个区放多少个元素,由用户分配(例如:只收不发可以把接收区拉满;只发不收的网关可以把发送区拉满,大大提高了内存的利用率)
4.1.1 缓冲区的分区与元素上限
注:1 字 = 4 字节 = 32 位
各分区按固定顺序依次排布,元素上限如下:
| 分区 | 元素数上限 | 每元素大小 | 区上限 |
|---|---|---|---|
| 11-bit 标准过滤器 | 0~128 | 1 字 | 128 字 |
| 29-bit 扩展过滤器 | 0~64 | 2 字 | 128 字 |
| Rx FIFO 0 | 0~64 | 4~18 字 | 1152 字 |
| Rx FIFO 1 | 0~64 | 4~18 字 | 1152 字 |
| Rx 专用缓冲 | 0~64 | 4~18 字 | 1152 字 |
| Tx Event FIFO | 0~32 | 2 字 | 64 字 |
| Tx 缓冲(专用 + FIFO/队列) | 0~32 | 4~18 字 | 576 字 |
| 触发存储(TTCAN 用) | 0~64 | 2 字 | 128 字 |
每元素的字数由数据场长度决定:元素 = 2 字头信息(ID、DLC、控制位)+ 数据字。
| 数据场(字节) | 0~8 | 12 | 16 | 20 | 24 | 32 | 48 | 64 |
|---|---|---|---|---|---|---|---|---|
| 计算(2 字头 + 数据字) | 2 + 2 | 2 + 3 | 2 + 4 | 2 + 5 | 2 + 6 | 2 + 8 | 2 + 10 | 2 + 16 |
| 元素大小(字) | 4 | 5 | 6 | 7 | 8 | 10 | 14 | 18 |
- 把所有区都拉满,单个控制器就需要约 17.5KB,比 10KB 的总量还大。所以 FDCAN 的分区配置本质上是一道预算题:各区元素数 × 元素字数之和不能超 2560 字,重叠了硬件不会替你检查,收发必然错乱。
- FDCAN 的消息 RAM 是按 4 字节一个字来编号、寻址的,而不是单独字节。配置起始地址时填“字地址”,不是“字节地址”。地址字段只看 bit15~bit2,最低两位无效,因此地址天然按 4 字节对齐。
- FDCAN 不会检查消息 RAM 的配置是否存在错误。因此配置不同部分的起始地址以及各部分 的元素数时必须多加留意,以免造成数据入侵或丢失。
5. 发送处理

发送处理单元处理专用发送缓冲区、发送 FIFO 和发送队列的发送请求。它控制着发送消息 到 CAN 内核的传输、放入和获取索引以及发送事件 FIFO,最多可为消息发送设置 32 个发送缓冲区(请参见 RAM 分配专用发送缓冲区)。根据 TXESC 寄存器 TBDS 字段配置的数据场大小,会使用 2 到 16 个 32 位字来存储 CAN 消息数据字段;加上 2 字头信息,每个发送元素共 4~18 字。
| 机制 | 规则 | 适合场景 |
|---|---|---|
| 专用 Tx Buffer | 每个缓冲对应一条报文,地址固定,随时整帧覆盖重发 | 高优先级报文的"抢占式"重发 |
| Tx FIFO | 先请求先发送(先来后到) | 一般数据流 |
| Tx Queue | 待发报文里 ID 最小的先发 | 需要保仲裁优先级时 |
FIFO 和 Queue 二选一,不能同时用;专用缓冲可以和 FIFO/Queue 共存,且专用缓冲排在 RAM 前段、FIFO/Queue 排在后段。
5.1 专用发送缓冲区
[开始]
│
▼
[更新专用发送缓冲区的数据]
│
▼
[触发发送请求]
│
▼
[内部仲裁] <═══ 与“发送 FIFO”或“发送队列”中的消息竞争
│
▼
[外部仲裁] <═══ 与“CAN 总线”上的消息竞争
│
▼
[根据消息 ID 发送出去]
-----------------------------------------------------------
注:如果在同一内部仲裁池中有多个专用缓冲区使用相同 ID,
编号最小的缓冲区将优先获得发送权。
- 控制权:完全受 CPU 控制发送。
- 优先级规则:多个缓冲区配置相同 ID 时,编号最小的缓冲区优先发送。
- 触发机制:数据更新后,需手动触发发送请求。
- 双重仲裁:
- 内部仲裁:与发送 FIFO、发送队列中的消息竞争。
- 外部仲裁:胜出后,与 CAN 总线上的现有消息竞争。
- 发送:最终根据消息 ID 发送出去。
5.2 发送 FIFO
流程图
[初始化] 配置 FIFO 模式 (TFQM = 0)
│
▼
[主循环] 等待操作
│
├─► 【写入消息】
│ │
│ ├─► 检查空闲级别 TXFQS.TFFL == 0?(即已满,TFQF = 1)
│ │ ├─► [是] 等待获取索引递增(暂停写入)
│ │ └─► [否] 继续执行
│ │
│ ├─► 写入 n 条数据至放入索引引用的缓冲区
│ ├─► 放入索引循环递增 n 位
│ └─► 置位 TXBAR,请求发送
│
├─► 【发送消息】
│ │
│ ├─► 检查是否有挂起请求?(TXBRP 对应位)
│ │ ├─► [否] 无消息可发,返回主循环
│ │ └─► [是] 继续执行
│ │
│ ├─► 发送获取索引引用的消息
│ └─► 获取索引循环递增
│
└─► 【取消发送】
│
├─► 检查:取消的是获取索引处的请求吗?
│ ├─► [是] 获取索引跳至下一个有请求的缓冲区
│ └─► [否] 状态保持不变
│
└─► 重新计算空闲级别(仅针对[是]的分支)
===========================================================
[统一更新]
空闲级别由硬件维护在 TXFQS.TFFL,软件直接读取,无需自己计算
===========================================================
补充:发送缓冲区地址计算
===========================================================
下一可用(空闲)发送缓冲区起始地址 =
消息 RAM 基址 + 发送缓冲区起始地址(TXBC.TBSA) + (放入索引 × 元素字数)
(注:元素字数 = 2 字头信息 + 数据字数,数据场 0~8 字节时为 4 字,
12/16/20/24/32/48/64 字节时分别为 5/6/7/8/10/14/18 字。
只有元素按最小 4 字配置时才能写成"放入索引 × 4"。)
- 发送机制:从“获取索引”处开始顺序发送,每发一条索引循环加一。空闲级别 = 放入索引 - 获取索引(代表剩余可用空间)。
- 写入与满状态:新消息写在“放入索引”处,写完索引加一。当放入索引追上获取索引时,FIFO已满,必须等发送完(获取索引增加)才能继续写。
- 请求发送:写入后需触发发送请求。支持一次写入并请求多条(n条),但请求数量不能超过当前“空闲级别”。
- 取消发送:若取消当前“获取索引”处的发送,索引会自动跳到下一个有请求的位置并重算空闲级别;若取消其他位置,状态不变。
- 地址计算:下一可用地址 = 消息 RAM 基址 + 发送缓冲区起始地址 + 放入索引 × 元素字数(元素 4~18 字,由 TXESC 配置的数据场大小决定,见 4.1.1)。
5.3 发送队列
[配置为发送队列模式]
│
├─► 【常规写入】
│ │
│ ├─► 检查队列是否已满
│ │ ├─► [是] 等待(直到有消息发出或请求取消)
│ │ └─► [否] 继续执行
│ │
│ ├─► 写入“放入索引”指向的缓冲区
│ └─► 放入索引循环递增
│
├─► 【灵活写入】
│ │
│ └─► 查找无挂起请求的缓冲区 -> 直接写入
│
▼
【发送仲裁】(按优先级规则)
│
├─► 规则 1:比较消息 ID,ID 越小优先级越高
└─► 规则 2:ID 相同时,比较缓冲区编号,编号越小优先级越高
│
▼
[发送消息]
===========================================================
补充:发送队列缓冲区地址计算
===========================================================
下一可用地址 = 消息 RAM 基址 + 队列起始地址(TXBC.TBSA) + (放入索引 × 元素字数)
(注:元素字数同 5.2,4~18 字,由 TXESC 配置决定)
- 配置与发送顺序:配置为队列模式后,系统按消息 ID 从小到大(优先级由高到低)发送。如果 ID 相同,则缓冲区编号小的先发送。
- 常规写入:新消息写入“放入索引”处,写完索引循环递增。如果队列已满,索引无效,必须等到有消息发出或请求取消后才能继续写入。
- 特殊写入(灵活写入):应用可以绕过“放入索引”,直接指定将消息放入任何没有挂起请求的空闲缓冲区中。
- 地址计算:下一空闲地址 = 消息 RAM 基址 + 队列起始地址 + 放入索引 × 元素字数(同 5.2)。
5.4 混合专用发送缓冲区/发送 FIFO
在这种情况下,消息 RAM 中的发送缓冲区部分会被划分为一组专用发送缓冲区和一个发送 FIFO。如果分配给发送 FIFO 的发送缓冲区数量配置为 0,则仅会使用专用发送缓冲区。

发送优先次序:
- 扫描专用发送缓冲区和时间最久的挂起发送 FIFO 缓冲区
- 消息 ID 最小的缓冲区优先级最高,下次将发送该缓冲区的数据
5.5 混合专用发送缓冲区/发送队列
在这种情况下,消息 RAM 中的发送缓冲区部分会被划分为一组专用发送缓冲区和一个发送队列。如果分配给发送队列的发送缓冲区数量配置为 0,则仅会使用专用发送缓冲区。

发送优先级设置:
- 扫描所有激活了发送请求的发送缓冲区
- 消息 ID 最小的发送缓冲区优先级最高,下次将发送该缓冲区的数据
5.6 发送暂停
发送暂停功能适用于以下 CAN 系统:其 CAN 消息标识符被永久指定为特定值,且难以更改。这些消息标识符对应的 CAN 仲裁优先级可能高于其他已定义消息,但在特定应用中,其相对仲裁优先级需要反转。此时可能出现如下问题:某一 ECU 发送的 CAN 消息突发会延迟另一 ECU 中仲裁优先级较低的 CAN 消息。
举例来说,如果 CAN ECU-1 启用了这个功能,并且它的应用软件请求发送 4 条消息:
[ECU 请求连续发送多条消息]
│
▼
[发送第 1 条消息]
│
▼
[发送完成] ──► [进入强制等待期] (时长为 2 个 CAN 位时间)
│
├─► [其他 ECU 有挂起消息?]
│ ├─► [是] 其他 ECU 抢占总线并发送消息
│ │ │
│ │ ▼
│ │ [总线释放] ──► [原 ECU 继续发送下一条消息]
│ │
│ └─► [否] 等待期满 ──► [原 ECU 继续发送下一条消息]
│
▼
[重复上述间隔机制,直至所有消息发送完毕]
此功能可使来自单个节点的突发发送变得松散一些,避免出现应用程序错误地请求过多传输的“胡乱指示”情况。
5.7 发送取消
FDCAN 通过 TXBCR 寄存器请求取消挂起的发送。对发送 FIFO,取消仅对获取索引处的报文有效(流程见 5.2 的取消分支);专用发送缓冲区和发送队列则可对任意挂起的缓冲区发起取消。
- 如果已经在从发送缓冲区进行发送时请求发送取消,则只要发送正在进行中,状态标志位保持置 1 状态。
- 如果发送成功,成功和取消标志位置位为 1。
- 如果发送不成功,则不会重复发送,仅将取消标志位置位为 1。
注:如果在挂起的发送尚未开始之前立即取消此次发送,即使该节点中有另一消息挂起,取消后也会有一个短暂的时间窗,在此期间不会开始任何发送。这样一来,另一节点便可以发送优先级可能比该节点中第二条消息低的消息。
5.8 发送事件处理
为了支持发送事件处理,FDCAN 实现了发送事件 FIFO。FDCAN 在 CAN 总线上发送消息后,消息 ID 和时间戳会存储在发送事件 FIFO 元素中。为了将发送事件关联到发送事件 FIFO 的元素,会将已发送的发送缓冲区中的消息标志复制到发送事件 FIFO 元素中。
用途:
将处理发送状态信息与处理发送消息分开,也就是让发送缓冲区仅保存要发送的消息,而将发送状态单独存储在发送事件 FIFO 中。
尤其是在处理动态管理的发送队列时,发送缓冲区可在发送成功后立即用于新消息。覆盖发送缓冲区之前,不需要保存该发送缓冲区的发送状态信息。
【写入事件】
│
▼
检查 FIFO 状态
│
├─► 【已满】 ──► 丢弃该事件 ──► 触发“事件丢失”中断
│
├─► 【未满】 ──┬─► 写入事件
│ │
│ └─► 检查是否达到“水印级别” ──► [是] 触发“水印中断”
│
▼
【读取事件】(由主机发起)
│
├─► 计算读取地址:起始地址 + (获取索引 × 2)
├─► 读取数据
└─► 获取索引递增(释放空间,允许继续写入)
- 满状态与溢出保护
- 禁止写入:当发送事件 FIFO 处于“满”状态时,在至少读取一个元素(获取索引递增)之前,禁止继续写入新元素。
- 事件丢弃:如果在已满状态下依然发生发送事件,该事件会被直接丢弃,并触发“事件丢失”中断标志。
- 水印预警:为了避免 FIFO 溢出,系统提供“水印”机制。当 FIFO 的填充级别达到设定的水印值时,会触发“水印中断标志”,提醒主机及时读取数据。
- 读取与地址计算
- 数据读取:读出数据时,需根据当前“获取索引”计算地址。
- 计算规则:当前读取地址 = 发送事件 FIFO 起始地址 + (获取索引 × 2)。(注:每个事件元素占用 2 个字)
6. 接收处理
接收处理单元控制着验收过滤、已接收消息到接收缓冲区或其中一个接收 FIFO(共两个)的传输以及接收 FIFO 放入和获取索引。FDCAN 可以配置验收过滤器,这个后文会再详细展开,这里着重说明整个接收处理流程(标准/扩展消息 ID 的过滤路径图随第 7 节过滤器正文一起讲)。
6.1 接收 FIFO
接收 FIFO 0 和接收 FIFO 1 最多可分别保存 64 个元素。
【接收消息(写入)】
│
▼
检查 FIFO 状态
│
├─► 【已满】 ──► 丢弃该消息 ──► 触发“消息丢失”中断
│
├─► 【未满】 ──┬─► 写入消息
│ │
│ └─► 检查是否达到“水印级别” ──► [是] 触发“水印中断”
│
▼
【读取消息】(由主机发起)
│
├─► 计算读取地址:起始地址 + (获取索引 × 元素大小)
├─► 读取数据
└─► 获取索引递增(释放空间,允许继续写入)
- 满状态保护:当接收 FIFO 已满时,在至少读取一条消息(获取索引递增)之前,禁止继续写入。若在已满状态下收到新消息,该消息会被直接丢弃,并触发“消息丢失”中断标志。
- 水印预警:为防止 FIFO 溢出,可设置水印阈值。当 FIFO 的填充级别达到设定的水印值时,会触发“水印中断”标志,提醒主机及时读取。
- 读取地址计算:读取消息时,当前数据的物理地址 = 接收 FIFO 起始地址 + 获取索引 × FIFO 元素大小。
6.2 接收 FIFO 阻止模式
【接收写入流程】
│
▼
[新消息到达]
│
▼
检查状态:检查 RXF0S.F0F(FIFO 满标志)是否为 1?
│
├─► 【是:已满】
│ │
│ ├─► 丢弃该新消息
│ └─► 触发“消息丢失”中断
│
└─► 【否:未满】
│
├─► 将消息写入 FIFO
├─► 放入索引递增
└─► 再次检查是否满状态? ──► [是] 触发“FIFO满”中断
【读取解锁流程】(主机操作)
│
▼
[主机读取一条消息]
│
▼
获取索引递增
│
▼
[解除满状态锁定] ──► 允许继续写入新消息
- 满状态判定与锁定
当填充级别达到 FIFO 元素总数(RXF0S.F0F = 1)时判定为已满。
- 锁定写入:此时将禁止继续写入新消息。
- 解除锁定:直到主机读取至少一条消息(获取索引递增)后,才能恢复写入。
- 中断触发:进入满状态时,会触发“FIFO 满”中断。
- 溢出与消息丢失
如果在已满状态下仍然接收到新消息,系统将执行以下操作:
- 直接丢弃该消息。
- 触发“消息丢失”中断,以警告主机发生了溢出。
6.3 接收 FIFO 覆盖模式
【写入侧:发生接收事件】
│
▼
检查 FIFO 是否已满?
│
├─► 【否:未满】 ──► 写入当前放入索引位置 ──► 放入索引 +1
│
└─► 【是:已满】 ──► 覆盖最旧的消息 ──► 放入索引 +1,获取索引 +1 (维持满状态)
-----------------------------------------------------------
【读取侧:主机读取数据】
│
▼
读取地址 = 起始地址 + (获取索引 × 元素字数)
│
▼
[读取数据] (注意:覆盖模式下读取时元素可能恰好被新报文覆盖,
对一致性有要求的应用应改用阻止模式或专用接收缓冲区)
-----------------------------------------------------------
【确认与解锁】
│
▼
将最后读取的元素编号写入“确认索引”
│
▼
更新获取索引至该确认位置
│
▼
检查:获取索引 == 放入索引?
│
├─► 【是】 ──► 清除满状态标志 (解除锁定,恢复常规写入)
└─► 【否】 ──► 保持满状态标志 (继续覆盖旧数据)
- 满状态下的覆盖写入
- 当 FIFO 已满时,如果再次收到新消息,系统会自动覆盖最旧的消息。
- 每覆盖写入一次,放入索引和获取索引都会同步加 1,形成动态滑动窗口。
- 读取一致性
- 覆盖模式下,读取期间“获取索引”处的元素可能恰好被新收到的报文覆盖。对数据一致性有要求的应用应改用阻止模式(6.2)或专用接收缓冲区(6.4)。
- 读取确认与满状态解除
- 每次读取完毕后,主机必须将最后读取的元素编号写入“确认索引”。
- 这会将获取索引直接推进到该确认位置。
- 当获取索引追上放入索引时,说明 FIFO 中有了新的可用空间,满状态标志会自动解除。
6.4 专用接收缓冲区
FDCAN 支持多达 64 个专用接收缓冲区。
对于每个接收缓冲区,必须配置标准或扩展消息 ID 过滤器元素。
接收到的消息被过滤器元素接受后,会存储在过滤器元素引用的消息 RAM 中的接收缓冲区中。存储格式与接收 FIFO 元素的格式相同。此外,中断寄存器中的标志 IR.DRX(专用接 收缓冲区中存储的消息)也会置 1。
【硬件接收与锁定流程】
│
▼
[收到匹配的消息,数据写入 RAM]
│
▼
[硬件自动将对应的 NDAT 标志置 1]
│
▼
[该接收缓冲区被锁定]
│
├─► 拒绝新数据覆盖当前缓冲区
└─► 对应的过滤器元素失效(不再匹配此缓冲区)
│
▼
[后续新消息到来] ──► 根据过滤器配置重新分配:
├─► 存入其他空闲缓冲区
├─► 存入接收 FIFO
└─► 被拒绝
【主机读取与解锁流程】(CPU 操作)
│
▼
[主机读取并处理完缓冲区数据]
│
▼
[主机向 NDAT 标志位写入“1”进行复位]
│
▼
[缓冲区解锁] ──► 对应的过滤器元素恢复匹配功能
- 自动置位与锁定
- 当匹配的消息最后一个字写入消息 RAM 后,硬件会自动将该缓冲区对应的“新数据标志 (NDAT)”置 1。
- 只要该标志保持为 1,对应的接收缓冲区就会被锁定,即使收到新的匹配帧也不会覆盖更新原有数据。
- 过滤跳过机制
- 缓冲区被锁定(NDAT=1)期间,指向该缓冲区的过滤器元素会失去匹配作用。
- 新的匹配消息会根据过滤器的配置,被分配到其他空闲缓冲区、接收 FIFO,或者被直接拒绝。
- 主机复位解锁
- 必须由主机(CPU)介入,将对应的标志位写入“1”来手动复位(清零)。
- 复位后,该缓冲区解除锁定,对应的过滤器元素重新恢复匹配功能。
6.5 接收缓冲区处理
- 复位中断标志 IR.DRX
- 读取新数据寄存器
- 从消息 RAM 中读取消息
- 复位已处理消息的新数据标志
7. 过滤器


上图:标准过滤器元素(手册表 469,占消息 RAM 1 个字);下图:扩展过滤器元素(手册表 471,占 2 个字)。每个元素(标准最多 128 个、扩展最多 64 个,各一套、互不影响)拥有:
- SFID1/SFID2(扩展为 EFID1/EFID2)两个 ID 槽——放 ID、范围端点还是屏蔽码,由类型字段决定;
- SFT/EFT 匹配类型:范围 / 双 ID / 经典屏蔽三选一;
- SFEC/EFEC 匹配后动作:存入 FIFO0/1、专用接收缓冲区,或直接拒绝;
- SFEC/EFEC = 000 即禁用该元素,相当于 bxCAN 的 FACTx = 0(不用的关掉,防误动作)。
位域排布(写裸值时参考,用 HAL 的
FDCAN_FilterTypeDef配置则完全不用管这些位):
- 标准元素(1 字):
SFT[1:0] | SFEC[2:0] | SFID1[10:0] | 保留 | SFID2[10:0]- 扩展元素(2 字):
F0 = EFEC[2:0] | EFID1[28:0],F1 = EFT[1:0] | 保留 | EFID2[28:0]——注意 EFEC 在第 1 个字、EFT 在第 2 个字,位置不对称,手写裸寄存器值时容易搞混。
先说整体结构:bxCAN 的过滤器是“寄存器 + 组合”——14 组寄存器靠 FSCx(位宽)× FBMx(模式)组合出 4 种模式;FDCAN 的过滤器是“消息 RAM 里的两张列表”——标准帧查 11-bit 列表(SIDFC 寄存器给出起始地址 FLSSA 和列表长度 LSS,最多 128 个元素)、扩展帧查 29-bit 列表(XIDFC 的 FLESA/LSE,最多 64 个元素),也就是 4.1.1 分区表的前两行。每个元素自带匹配类型(SFT/EFT)和匹配后动作(SFEC/EFEC),另有一个全局寄存器 GFC 处理“都不匹配”的情况。
bxCAN 与 FDCAN 的过滤器对比:
| 对比项 | bxCAN(F103) | FDCAN(H757) |
|---|---|---|
| 过滤器数量 | 14 组(互联型 28) | 标准 128 元素 + 扩展 64 元素 |
| 存放位置 | 过滤器寄存器 | 消息 RAM 中的两张列表 |
| 匹配能力 | 列表 / 屏蔽(位宽组合出 4 种) | 范围 / 双 ID / 经典屏蔽 |
| 帧类型匹配 | ID + IDE + RTR 一起比 | 只比 ID(IDE 由查哪张列表决定,RTR 全局处理) |
| 报文去向 | FFA 二选一(FIFO0/1) | 每元素独立路由:FIFO0/1、专用缓冲区、直接拒绝 |
| 都不匹配时 | 丢弃 | 由 GFC 全局配置:收进 FIFO0/1 或拒收 |
7.1 两张列表的执行规则
FDCAN 可配置两组验收过滤器,分别用于标准标识符和扩展标识符。一帧报文进来,IDE 位决定查哪张表:标准帧(IDE=0)走 11-bit 列表,扩展帧(IDE=1)走 29-bit 列表——这就是对比表里“IDE 由查哪张列表决定”的含义。bxCAN 里 IDE 是过滤器映像中参与匹配的一个位;FDCAN 里它只负责分流,不参与比较。
列表从第 0 个元素开始依次执行,找到第一个匹配的元素后过滤立即停止,不再评估该消息的后续过滤器元素。这条规则的直接推论:规则有重叠时,排在前面的说了算——若元素 0 配了“0x100~0x1FF 进 FIFO0”、元素 1 配了“0x123 拒绝”,0x123 实际会进 FIFO0(元素 0 先命中);想让拒绝生效,就得把它挪到前面。
标准消息 ID 的过滤路径:

扩展消息 ID 的过滤路径:

两张路径图逐分支读下来就四步:
- 先拦远程帧:GFC.RRFS/RRFE = 1 时,标准/扩展远程帧直接丢弃(全局开关,标准、扩展各一位);= 0 放行,进入下一步;
- 查对应列表:列表长度 LSS/LSE = 0(空表)时整个列表跳过,直接走第 4 步;
- 命中:按该元素的 SFEC/EFEC 执行(接受或拒绝,见 7.3);接受的还要看目标 FIFO 满没满——满了照样丢弃帧;
- 全不匹配:由 GFC.ANFS/ANFE 决定——收进 FIFO0(00)、FIFO1(01)或拒收(10)。
GFC(全局过滤器配置)是 bxCAN 没有的东西:bxCAN“都不匹配 = 丢弃”是焊死的;FDCAN 把这一步做成可配,还顺带管远程帧的全局拒收。调试期想让所有帧都进来:列表留空 + ANFS/ANFE = 00 即可,一个过滤器元素都不用占(bxCAN 文章例 6 还得专门占一组屏蔽码全 0 的过滤器)。
主要特性(手册归纳):
- 每个过滤器元素可配置为:
- 范围过滤器(起止范围)
- 用于一个或两个专用 ID 的过滤器
- 典型位屏蔽过滤器
- 每个过滤器元素均可配置为实现验收过滤或拒绝过滤(同一个列表里黑白名单可以混着用)
- 每个过滤器元素均可单独使能/禁止
- 会按顺序检查过滤器,过滤出第一个匹配的过滤器元素后会停止执行
7.1.1 验收过滤的时机与错误帧处理
CAN 协议控制器接收到完整标识符后启动验收过滤。若验收过滤找到匹配的接收缓冲区或接收 FIFO,消息处理单元随即开始按 32 位形式将接收消息数据写入该匹配对象。
若 CAN 协议控制器检测到错误条件(例如 CRC 错误),则丢弃该消息。丢弃后的影响如下:
- 接收缓冲区:匹配接收缓冲区的新数据标志不会置 1,但该缓冲区(可能部分)会被接收到的数据覆盖。错误类型参见 PSR.LEC 和 PSR.DLEC。
- 接收 FIFO:匹配接收 FIFO 的放入索引不会更新,但相关 FIFO 元素(可能部分)会被接收到的数据覆盖。错误类型参见 PSR.LEC 和 PSR.DLEC。若匹配的接收 FIFO 工作在覆盖模式,还需考虑“接收 FIFO 覆盖模式”中所述的边界条件。
7.2 匹配类型三选一(SFT/EFT)
SFT[1:0]/EFT[1:0] 决定 SFID1/SFID2 两个槽怎么用:
| 编码 | 模式 | SFID1 / EFID1 | SFID2 / EFID2 |
|---|---|---|---|
| 00 | 范围过滤 | 范围下限 | 范围上限 |
| 01 | 双 ID 过滤 | ID ① | ID ② |
| 10 | 经典屏蔽 | ID 模板 | 屏蔽码(1=必须一致,0=无关) |
| 11 | 范围过滤,不使用 XIDAM(仅扩展 ID 有此编码) | 范围下限 | 范围上限 |
编码值与 HAL 宏一一对应:
FDCAN_FILTER_RANGE / DUAL / MASK / RANGE_NO_EIDM(stm32h7xx_hal_fdcan.h)。另外注意术语:手册叫 XIDAM,HAL 注释里叫 EIDM,同一个东西。
怎么选——沿用 bxCAN 文章例 3 的决策规则,由想要接收的 ID 决定,不由总线上存在什么决定:
- 要收的 ID 连续成段(如 0x200~0x2FF)→ 范围,写下限上限就行;
- 要收的 ID 少而离散 → 双 ID,一个元素顶两个;
- 要收的 ID 有共同位规律但不连续(如一段里挑奇数)→ 经典屏蔽;
- 实在没有规律就多分几个元素:标准 128 个(双 ID 再翻倍成 256 个 ID)、扩展 64 个——bxCAN 只有 14 组要省着用,FDCAN 一般用不完。
7.2.1 范围过滤器(SFT/EFT = 00)
该过滤器会将所有接收到的帧与过滤寄存器定义的范围内的消息 ID 进行匹配检查。SFID1 = 范围下限,SFID2 = 范围上限,ID 落在 [SFID1, SFID2] 内即命中。bxCAN 想收一段得算屏蔽码(收 0x200~0x2FF 要写 (0x700<<5)|0x10|0x8 这么一串),FDCAN 直接把两个端点写进去,是最直观的改进。
扩展 ID 用范围过滤时多一个细节,分两种情况:
- EFT =“00”:应用范围过滤器之前,会将已接收帧的消息 ID 与扩展 ID 与掩码 (XIDAM) 进行与运算,再拿结果与 EFID1/EFID2 比较——适合“只关心 ID 的某些位、其余位怎么变都行”的范围;
- EFT =“11”:不会为范围过滤使用扩展 ID 与掩码 (XIDAM),收到的 29 位 ID 原样与 EFID1/EFID2 比较。
7.2.2 专用 ID 过滤器(SFT/EFT = 01)
可将过滤器元素配置为过滤一个或两个特定的消息 ID——对应 bxCAN 的列表模式:SFID1、SFID2 各装一个精确 ID,报文 ID 等于其中任意一个即命中。一个元素装两个 ID,标准列表 128 个元素最多容纳 256 个离散 ID。
bxCAN 的 16 位列表模式一个过滤器组能装 4 个标准 ID,单组看着更多——但它总共只有 14 组,且装 ID 还得左移 5 位对齐映像;FDCAN 的 SFID1/SFID2 就是 11 位/29 位 ID 本身(HAL 里 FilterID1/FilterID2 的取值范围就是 0~0x7FF / 0~0x1FFFFFFF),直接写、不用移位。
7.2.3 经典位屏蔽过滤器(SFT/EFT = 10)
典型位屏蔽过滤通过屏蔽已接收消息 ID 的个别位,实现对一组消息 ID 的过滤。配置时,SFID1/EFID1 用作消息 ID 过滤器(模板),SFID2/EFID2 用作过滤器屏蔽位。
屏蔽规则如下:
- 屏蔽位为 0:已接收消息 ID 中对应位不参与验收过滤,是 0 是 1 都行;
- 屏蔽位为 1:已接收消息 ID 中对应位参与验收过滤,需与 ID 过滤器对应位一致。
边界情况:
- 若所有屏蔽位均为 1,则仅当接收到的消息 ID 与消息 ID 过滤器完全相同时才匹配——退化为精确匹配(相当于双 ID 模式只用一个槽);
- 若所有屏蔽位均为 0,则所有消息 ID 均匹配——“全通过”的一种写法(更省的写法见 7.4 例 6)。
场景沿用 bxCAN 文章 8.3 的温度/湿度探头:要收 0x100~0x1FF 全部温度——连续段用范围过滤器直接写端点就行;屏蔽模式的用武之地是位有规律但值不连续,比如“0x100~0x1FF 里只要 bit0=1 的奇数 ID”:模板 SFID1=0x101、屏蔽码 SFID2=0x701(高 3 位必须是 001、bit0 必须是 1,中间 7 位随意)——这种按位挑选的需求,范围过滤器表达不了,屏蔽才行。
bxCAN 的思维转换:bxCAN 的 32 位映像里 IDE、RTR 跟 ID 挤在一起比,能靠 0x4/0x2 位配出“只要扩展帧”“只要遥控帧”;FDCAN 的过滤器只比 ID——帧格式的事被分流走了:IDE 负责决定查哪张表(想只收扩展帧?标准列表留空、GFC.ANFS=10 拒收即可),RTR 归 GFC.RRFS/RRFE 全局处理。“只要遥控帧”这种需求在过滤器层面做不到,只能放行后软件按 RTR 位再分拣(见 7.4 例 5)。
7.3 匹配后的动作(SFEC/EFEC)
bxCAN 的 FFA 位只有“FIFO0 还是 FIFO1”二选一;FDCAN 把去向做进了每个元素的动作字段。根据过滤器元素配置(SFEC/EFEC),匹配发生后将执行以下互斥操作之一:
| 编码 | 匹配后的动作 |
|---|---|
| 000 | 禁用该元素 |
| 001 | 将接收帧存入 FIFO0 |
| 010 | 将接收帧存入 FIFO1 |
| 011 | 拒绝该接收帧(过滤器还能当黑名单用) |
| 100 | 仅将高优先级消息中断标志 IR.HPM 置 1 |
| 101 | 将 IR.HPM 置 1,并将接收帧存入 FIFO0 |
| 110 | 将 IR.HPM 置 1,并将接收帧存入 FIFO1 |
| 111 | 将接收帧存入接收缓冲区(该元素指向的缓冲区,NDAT 锁定机制见 6.4;此编码下 SFT/EFT 类型字段被忽略) |
手册中“存入接收缓冲区并在过滤器事件引脚上生成脉冲”也归 111。编码值已按 HAL 宏核对(FDCAN_FILTER_DISABLE / TO_RXFIFO0 / TO_RXFIFO1 / REJECT / HP / TO_RXFIFO0_HP / TO_RXFIFO1_HP / TO_RXBUFFER)。
7.4 配置示例
沿用 bxCAN 文章 8.4 的六个场景改写成 FDCAN 版(均假定收进 FIFO0,即 SFEC=001;bxCAN 那套 R1/R2 左移对齐计算全部消失):

| 总线上存在的 ID | 想要接收的 ID | 过滤器配置 |
|---|---|---|
| 0x123/234/345/456/567/678 | 0x234、0x345、0x567 | 元素0:SFT=01,SFID1=0x234、SFID2=0x345;元素1:SFT=01,SFID1=SFID2=0x567 |
| 0x1000x1FF、0x2000x2FF、0x310~0x32F | 0x200~0x2FF + 0x320~0x32F | 元素0:SFT=00,SFID1=0x200、SFID2=0x2FF;元素1:SFT=00,SFID1=0x320、SFID2=0x32F |
| 标准 0x123/234/345 + 扩展 0x12345678、0x0789ABCD | 0x123 + 0x12345678 | 标准列表元素0:SFT=01,SFID1=SFID2=0x123;扩展列表元素0:EFT=01,EFID1=EFID2=0x12345678——两张表各管各的 |
| 0x123456000x123456FF、0x0789AB000x0789ABFF | 0x12345600~0x123456FF | 扩展元素0:EFT=00,EFID1=0x12345600、EFID2=0x123456FF |
| 任意 ID | 只要遥控帧 | 过滤器做不到:只比 ID,远程帧只能 GFC 全局拒收/放行,放行后软件按 RTR 位再分拣 |
| 任意 ID | 所有帧全通过(调试期) | 列表长度 LSS=0(空表)+ GFC.ANFS=00(非匹配进 FIFO0)——一个元素都不占 |
逐例点评:
- 例 1:bxCAN 得选 16 位列表、算左移 5 位,还得惦记“第 4 个槽填 0 的前提是总线上没有 ID=0 的帧”;FDCAN 一个双 ID 元素装俩,落单的 ID 两个槽填同一个值即可。
- 例 2:范围过滤器的典型场景。bxCAN 要写
(0x700<<5)|0x10|0x8和(0x7F0<<5)|0x10|0x8两组屏蔽码;FDCAN 直接写端点,两个不相邻的段就是两个元素、互不影响。 - 例 3:bxCAN 被迫上 32 位映像(标准 ID 左移 21 位、扩展 ID 左移 3 位再或 0x4);FDCAN 标准/扩展天然分表,各写各的 ID,不用移位。
- 例 4:扩展 ID 成段,EFT=00 范围过滤直填端点。
- 例 5:bxCAN 映像里有 RTR 位,能精确做到;FDCAN 把帧类型匹配从过滤器里拿走了(IDE 管分表、RTR 归 GFC),只能软件分拣。
- 例 6:bxCAN 得占一组过滤器写 FR2=0;FDCAN 的兜底是独立寄存器 GFC,空列表 + ANFS=00 即全通过,过滤器资源一个不占。
注意:列表长度只覆盖用到的元素;长度以内用不到的元素要显式配 SFEC=000 禁用,免得残留旧配置误匹配。
7.5 调试消息过滤(进阶,一般用不到)
要过滤调试消息,需为三个调试消息分别配置一个标准或扩展消息 ID 过滤器元素。使能过滤器元素过滤调试消息时,必须将 SFEC/EFEC 编程为“111”。
在该配置下,SFID1/SFID2 和 EFID1/EFID2 的含义有所不同:
- SFID2/EFID2[10:9]:控制调试消息处理状态机;
- SFID2/EFID2[5:0]:控制已接收调试消息的存储位置。
存储调试消息时,相应的新数据标志和 IR.DRX 均不会置 1。可通过 RXF1S.DMS 监视调试消息的接收情况。


8. 测试模式
8.1 内外部回环模式

8.2 受限模式
在受限工作模式下,节点能够接收数据帧和远程帧,并对有效帧进行确认,但不会发送数据帧、远程帧、有效错误帧或过载帧。若出现错误条件或过载条件,节点不会发送显性位,而是等待总线空闲条件,以便与 CAN 通信重新同步。当错误记录(ECR.CEL)激活时,错误计数器(ECR.REC、ECR.TEC)会冻结。
进入与退出
- 软件可通过将 CCCR.ASM 置 1 使 FDCAN 进入受限工作模式。仅当 CCCR.CCE 和 CCCR.INIT 均为 1 时,才能通过软件将 CCCR.ASM 置 1;该位可随时通过软件清零。
- 当发送处理单元无法及时从消息 RAM 中读取数据时,FDCAN 会自动进入受限工作模式。要退出受限工作模式,软件必须复位 CCCR.ASM。
典型用途
受限工作模式可用于需要根据 CAN 比特率进行自适应调整的应用。此类应用会测试不同比特率,并在收到有效帧后退出受限工作模式。
时钟校准控制
CCCR.ASM 也由时钟校准单元控制。时钟校准过程使能后,FDCAN 进入受限工作模式,CCCR.ASM 置 1;校准完成后,CCCR.ASM 清零。
注:受限工作模式不得与环回模式(内部或外部)结合使用。
8.3 总线监控模式
当 CCCR.MON 位置 1,或 FDCAN 进入错误级别 S3(TTOST[EL] = “11”)时,FDCAN 进入总线监控模式。

模式行为
- FDCAN 能够接收有效数据帧和有效远程帧,但不能启动发送过程。
- FDCAN 仅在 CAN 总线上发送隐性位。
- 若 FDCAN 需要发送显性位(如 ACK 位、过载标志或活动错误标志),该位会在内部改道发送,以便 FDCAN 仍可监视该显性位,而 CAN 总线保持隐性状态。
- 在总线监控模式下,寄存器 TXBRP 保持复位状态。
典型用途
总线监控模式可用于分析 CAN 总线流量,同时避免因发送显性位而对总线造成影响。
9. CAN-FD 概念
FDF 位与 CAN FD 比特率切换:
具有 11 位标识符的 CAN 帧中原保留位,以及具有 29 位标识符的 CAN 帧中原第一个保留位,现已解码为 FDF 位:
- FDF 为隐性:表示 CAN FD 帧;
- FDF 为显性:表示典型 CAN 帧。
在 CAN FD 帧中,FDF 之后的 res 位和 BRS 位决定是否在该 CAN FD 帧中切换比特率:
- res 为显性且 BRS 为隐性:表示进行 CAN FD 比特率切换;
- res 为隐性:该编码保留,供未来协议扩展使用。
协议异常处理:
若 M_TTCAN 接收到 FDF 为隐性且 res 为隐性的帧,则通过将 PSR.PXE 置 1 发出协议异常事件,并根据 CCCR.PXHD 的配置执行相应处理:
- 使能协议异常处理(CCCR.PXHD = 0):在下一采样点,工作状态从接收器(PSR.ACT = “10”)变为同步中(PSR.ACT = “00”);
- 禁止协议异常处理(CCCR.PXHD = 1):FDCAN 将隐性 res 位视为格式错误,并以错误帧进行响应。
9.1 FD 帧的三个新位
- FDF(Flexible Data Format):隐性表示这是 FD 帧(替代经典帧的 R1 保留位);
- BRS(Bit Rate Switch):隐性表示数据场切换到更高速率——仲裁段为稳妥保持 1Mbps,报文 ID 仲裁完成后,数据场和 CRC 段提速(最高 8Mbps),发完再降回来;
- ESI(Error State Indicator):发送节点是错误被动状态时置位,接收方借此知道发送端"状态不好"。
9.2 DLC 的非线性映射
经典帧 DLC 0~8 一一对应 0~8 字节;FD 帧 DLC 9~15 不再线性:

9.3 双相位位时序
因为一段帧里有两种速率,FDCAN 有两套独立的位时序参数:名义段(Nominal,管仲裁段)和数据段(Data,管 BRS 之后的数据场与 CRC 段),各自的预分频器、SJW、TSEG1/TSEG2 全部分开配(NBTP / DBTP 两个寄存器),本文不展开。
9.4 TDC 与 CCU

- TDC(收发器延迟补偿):数据段速率高时,发送节点回读自己发出的位已经滞后一截,采样点要用"二次采样点"补偿,这是 FD 高速率的配套机制,经典模式不用管;
- CCU(时钟校准单元):H7 上所有 FDCAN 实例共用一个 CCU,且只有 FDCAN1 能访问它的寄存器——多实例时别到 FDCAN2 里找。
10.中断
bxCAN 是 4 个固定中断向量(发送 / FIFO0 / FIFO1 / 状态错误);FDCAN 改成"事件 → 线"两级:每个事件一个标志,使能后可自由映射到中断线 0 或线 1,每个实例占 2 条中断线(IT0/IT1)对应 2 个 NVIC 向量;此外 FDCAN1 独占时钟校准中断向量 FDCAN1_CAL,所以 FDCAN1 实际占 3 个向量、FDCAN2 占 2 个。想要"高频事件走线 0 低优先级、紧急事件走线 1 高优先级"的分组策略,配一下映射就行。
(典型分配示例,实际每个事件经 ILS 寄存器自由选线)
| 中断 | 触发源 |
|---|---|
| FDCAN1 中断线 0 | 接收 FIFO0 新消息、接收 FIFO1 新消息、接收缓冲区新消息、高优先级消息、发送完成、发送取消完成、TX FIFO 空等事件 |
| FDCAN2 中断线 0 | 同 FDCAN1 中断线 0,对应 FDCAN2 实例的上述事件 |
| FDCAN1 中断线 1 | 接收 FIFO0/FIFO1 水位到达、接收 FIFO0/FIFO1 消息丢失、接收缓冲区消息丢失、错误/协议错误、总线关闭、仲裁丢失、超时、消息 RAM 访问失败、时间戳回绕等事件 |
| FDCAN2 中断线 1 | 同 FDCAN1 中断线 1,对应 FDCAN2 实例的上述事件 |
| 时钟校准单元 | 时钟校准单元事件,如校准完成/校准中断(CAL)等 |
触发事件:
| 类别 | 事件 |
|---|---|
| 发送 | 发送完成 / 取消完成 / Tx FIFO 空 |
| Rx FIFO0 | 新报文 / 达到水线 / FIFO 满 / 报文丢失(FIFO1 同名一套) |
| 错误状态 | Bus-Off 状态变化 / 错误警告 / 错误被动 |
| 协议错误 | 仲裁段协议错误 / 数据段协议错误 |
11. 错误处理和离线恢复
11.1 协议层状态机(与 bxCAN 相同)
TEC/REC 计数器的增减规则是 CAN 协议规定的,两代外设一致:
主动错误 ──(TEC或REC > 127)──> 被动错误 ──(TEC > 255)──> 总线关闭(Bus-Off)
▲ │
└──────────────(<恢复条件满足,计数器清零>)──────────────────┘
11.2 LEC:FDCAN 独有的错误原因码
bxCAN 出错只知道计数器变了,FDCAN 的 PSR 寄存器里有 LEC(最后错误码),直接给出错误原因:
| LEC | 含义 |
|---|---|
| 0 | 无错误(最近一次收发成功后会自动清 0) |
| 1 | 填充错误(不该连续等值的地方出现了 5+ 个相同位) |
| 2 | 格式错误(固定格式位域出错) |
| 3 | 应答错误(发的报文没人 ACK) |
| 4 | 位隐性错误(想发 1,总线上是 0) |
| 5 | 位显性错误(想发 0,总线上是 1) |
| 6 | CRC 错误 |
| 7 | 无变化(CPU 读过之后的空档状态) |
CAN-FD 帧数据段另有独立的 DLEC,编码相同。调试不通总线时先读 LEC,比猜快得多。
11.3 Bus-Off 恢复:必须软件拉一把
这是和 bxCAN 差异最大、最容易踩坑的地方:
- 进入:TEC 溢出 255 → 硬件自动置 CCCR.INIT=1,停止一切总线活动(PSR.BO 置位,可触发 Bus-Off 中断);
- 恢复:软件清零 CCCR.INIT 发起,之后硬件等待 129 次"总线空闲"(129 × 11 个连续隐性位)——比 bxCAN/CAN 规范的 128 次多一次;等待期间每检测到一次 11 个隐性位,LEC 会写一次 Bit0Error,可借此监控恢复进度;
- 恢复完成后 TEC/REC 清零、PSR.BO 清零,节点回到主动错误状态。
bxCAN 有 ABOM 位:置 1 即硬件自动完成整个恢复流程。FDCAN 没有等价位——Bus-Off 后如果软件不去清 INIT,节点就永远停在那里。标准姿势是在 Bus-Off 中断里清 INIT 发起恢复。
另外 CCCR.DAR(禁止自动重传)对应 HAL 的 AutoRetransmission = DISABLE:仲裁丢失或出错不自动重发、报文只发一次。
12. 工作模式、波特率
与 bxCAN 仅有微小差异,可以参考 bxCAN 文章:【双 MCU 架构车载仪表终端(CAN 互联)】STM32F1 bxCAN 外设
注意:在 bxCAN 基础上 FDCAN 的工作模式还多一层保护:CCE(配置改变使能)位。INIT=1 且 CCE=1 时才允许写位时序等关键配置寄存器——比 bxCAN 多一道"确认真的在初始化模式"的门。
博客导航
本文来自博客园,作者:膝盖中箭卫兵,转载请注明原文链接:https://www.cnblogs.com/hai-feng-dev/p/23513370

浙公网安备 33010602011771号
https://orcid.org/0000-0001-5102-772X