2.2 STM32 CAN外设(下)
2.2.1 标识符过滤器
本节将重点解决:如何配置过滤器的规则,使其准确过滤出我们想要的报文 ID?
过滤器基本功能回顾:
- 当管理员(硬件)接收到一个报文后,会将其 ID 与所有启用的过滤器进行比较。
- 如果报文 ID 匹配了任何一个启用过滤器的规则,则该报文被视为**“需要的”,允许通过过滤器,并存入指定的接收 FIFO** (
FIFO0
或FIFO1
)。 - 如果报文 ID 无法匹配任何一个启用过滤器的规则,则该报文被视为**“不需要的”,被直接丢弃**,不会存入 FIFO,也不会通知程序。这极大地减轻了软件处理无关报文的负担。
过滤器寄存器概览 (单个过滤器):
每个过滤器由一组寄存器控制其行为和规则:
- 核心过滤寄存器 (2个 32位):
FXR1
(Filter x register 1
, x=0…13):存储过滤器标识符/掩码的关键部分 1。FXR2
(Filter x register 2
, x=0…13):存储过滤器标识符/掩码的关键部分 2。- 作用:报文 ID 的关键过滤信息(目标 ID 或 ID + 掩码)存储在这两个寄存器中。具体格式取决于工作模式。
- 配置寄存器位:
FSCx
(Filter scale x
, x=0…13):过滤器位宽配置。0
:配置为 16 位 位宽模式。1
:配置为 32 位 位宽模式。
FBMx
(Filter mode x
, x=0…13):过滤器模式配置。0
:配置为 屏蔽模式 (Mask mode)。1
:配置为 列表模式 (List mode)。
- 作用:
FSCx
和FBMx
共同决定过滤器的工作模式(共 4 种),决定了FXR1
和FXR2
寄存器中数据的解释方式,从而定义过滤规则。
- FIFO 关联寄存器位:
FFAx
(Filter FIFO assignment x
, x=0…13):指定通过此过滤器的报文存入哪个 FIFO。0
:报文存入FIFO0
。1
:报文存入FIFO1
。
- 作用:实现报文分流(如重要报文进
FIFO0
,普通报文进FIFO1
)。
- 激活控制寄存器位:
FACTx
(Filter activation x
, x=0…13):过滤器激活开关。0
:禁用该过滤器。1
:启用该过滤器。
- 作用:未使用的过滤器应禁用 (
FACTx=0
),防止其意外干扰。需要时才启用 (FACTx=1
)。
注:寄存器名称中的
x
(如FXR1
,FSCx
) 表示该寄存器属于过滤器组x
(x = 0 到 13)。STM32 有 14 个独立的过滤器组,每个组都拥有自己的一套上述寄存器。
过滤器工作模式详解 (4种):
FSCx
(位宽) 和 FBMx
(模式) 的组合定义了过滤器的 4 种工作模式。不同模式适用于不同的过滤需求(单个精确 ID vs. 一组 ID)。
32 位列表模式 (
FSCx = 1
,FBMx = 1
):
- 设计思路:精确匹配特定的 1 个或 2 个 ID (标准或扩展)。
- 寄存器使用:
FXR1
:存储 第 1 个目标 ID 及其相关信息。FXR2
:存储 第 2 个目标 ID 及其相关信息。
FXR1/FXR2
寄存器位定义 (每个寄存器):[31:21]
STID[10:0]
:标准 ID (11位)。写入目标标准 ID 或扩展 ID 的高 11 位。[20:3]
EXID[17:0]
:扩展 ID 的低 18 位。仅在过滤扩展 ID 时使用。[2]
IDE
:标识符扩展位。0
:此寄存器存储的是标准 ID (仅使用STID[10:0]
)。1
:此寄存器存储的是扩展 ID (使用STID[10:0]
+EXID[17:0]
共 29 位)。
[1]
RTR
:遥控传输请求位。0
:此 ID 对应数据帧。1
:此 ID 对应遥控帧。
[0]
保留位:通常写0
。
- 配置示例:
- 过滤标准 ID
0x123
的数据帧:FXR1
=0x123 << 21
|IDE=0
|RTR=0
(即0x24600000
)。 - 过滤扩展 ID
0x1ABCDEF
的遥控帧:FXR2
=(0x1A << 21)
|(0xBCDEF << 3)
|IDE=1
|RTR=1
(计算具体值)。
- 过滤标准 ID
- 过滤逻辑:接收到的报文 ID 必须精确等于
FXR1
或FXR2
中配置的 ID (包括IDE
,RTR
),才能通过过滤器。 - 优缺点:简单直接,但每个过滤器最多只能过滤 2 个 ID。资源利用率较低(尤其当只过滤标准 ID 时,
EXID
18 位被浪费)。
16 位列表模式 (
FSCx = 0
,FBMx = 1
):
- 设计思路:优化资源,精确匹配多个 (最多 4 个) 标准 ID。将 32 位寄存器拆分为两个 16 位单元使用。
- 寄存器使用:
FXR1
拆分为:FXR1[31:16]
(单元 1A),FXR1[15:0]
(单元 1B)。FXR2
拆分为:FXR2[31:16]
(单元 2A),FXR2[15:0]
(单元 2B)。- 每个 16 位单元 可配置一个标准 ID 过滤项。
- 每个 16 位单元位定义:
[15:5]
STID[10:0]
:标准 ID (11位)。写入目标标准 ID。[4]
RTR
:遥控传输请求位。0
:过滤数据帧。1
:过滤遥控帧。
[3]
IDE
:标识符扩展位。必须设置为0
(仅过滤标准格式 ID)。[2:0]
EXID[17:15]
:扩展 ID 的高 3 位 (位17-15)。在 16 位模式下通常无效,设置为000b
。
- 配置示例:在
FXR1[15:0]
(单元 1B) 配置过滤标准 ID0x123
的数据帧:STID[10:0]
=0x123
,RTR=0
,IDE=0
,EXID[17:15]=000b
(即0x2460
)。其他单元类似配置。 - 过滤逻辑:接收到的报文必须是标准格式 (
IDE=0
),且其 ID 必须精确等于 四个单元中任何一个单元配置的标准 ID (包括RTR
),才能通过过滤器。 - 优缺点:专为过滤大量标准 ID 优化,一个过滤器可过滤 4 个 ID。无法过滤扩展 ID。
32 位屏蔽模式 (
FSCx = 1
,FBMx = 0
):
- 设计思路:过滤一组 ID。通过定义 ID 模板 (
FXR1
) 和 掩码/屏蔽位 (FXR2
) 来指定哪些 ID 位必须匹配,哪些位可以忽略(“无关位”)。 - 应用场景:过滤具有相同高位特征的一组 ID(如所有以
0x1
开头的标准 ID)。 - 寄存器使用:
FXR1
:存储 ID 模板 (Identifier)。定义期望匹配的位值。FXR2
:存储 掩码 (Mask)。定义哪些位需要严格匹配 (1
),哪些位可以忽略 (0
)。
FXR1
(ID 模板) 和FXR2
(掩码) 寄存器位定义 (相同):[31:21]
STID[10:0]
:标准 ID 部分。[20:3]
EXID[17:0]
:扩展 ID 的低 18 位。[2]
IDE
:标识符扩展位。[1]
RTR
:遥控传输请求位。[0]
保留位:通常写0
。
- 过滤逻辑 (按位操作):
- 对于接收报文 ID 的每一位 (包括
STID
,EXID
,IDE
,RTR
):- 如果
FXR2
(掩码) 的对应位 =1
,则接收报文的该位必须等于FXR1
(模板) 的对应位。 - 如果
FXR2
(掩码) 的对应位 =0
,则接收报文的该位可以是0
或1
(无关)。
- 如果
- 只有所有掩码位为
1
的位都匹配成功,报文才通过过滤器。
- 对于接收报文 ID 的每一位 (包括
- 配置示例 (过滤所有
0x1xx
标准数据帧):- 需求:标准 ID 高 3 位必须是
001b
(即0x1
),低 8 位任意 (xx
),IDE=0
(标准帧),RTR=0
(数据帧)。 FXR1
(模板):STID[10:0]
=00100000000b
(0x100
),IDE=0
,RTR=0
。EXID
写0
。 (值 ≈0x20000000
)。FXR2
(掩码):STID[10:8]
=111b
(高 3 位必须匹配),STID[7:0]
=00000000b
(低 8 位无关),IDE
位掩码 =1
(必须匹配标准帧),RTR
位掩码 =1
(必须匹配数据帧)。EXID
掩码写0
。 (值 ≈0x1C000000
注意掩码位位置)。
- 需求:标准 ID 高 3 位必须是
- 优缺点:极其强大,一个过滤器即可过滤大量具有相同特征的 ID。资源利用率高。要求项目在规划 ID 时将同组 ID 的关键特征位(通常是高位)设置为固定值。
- 设计思路:过滤一组 ID。通过定义 ID 模板 (
16 位屏蔽模式 (
FSCx = 0
,FBMx = 0
):
- 设计思路:结合 16 位宽度和屏蔽模式的优点,用于过滤两组标准 ID 范围。将 32 位寄存器拆分为两个 16 位单元使用,每个单元包含一个 ID 模板 + 掩码。
- 寄存器使用:
FXR1
拆分为:FXR1[31:16]
(单元 1A: 掩码),FXR1[15:0]
(单元 1B: ID 模板)。FXR2
拆分为:FXR2[31:16]
(单元 2A: 掩码),FXR2[15:0]
(单元 2B: ID 模板)。- 每个 ID 模板 (单元 1B/2B) 和其对应的 掩码 (单元 1A/2A) 组成一个独立的屏蔽过滤项。
- 每个 16 位单元位定义 (与 16 位列表模式相同):
[15:5]
STID[10:0]
:标准 ID 部分。[4]
RTR
:遥控传输请求位。[3]
IDE
:标识符扩展位 (必须为0
)。[2:0]
EXID[17:15]
:扩展 ID 的高 3 位 (通常无效,设000b
)。
- 过滤逻辑 (每个独立项):
- 对于接收报文 (必须是标准格式
IDE=0
) 的每一位 (STID
,RTR
):- 如果掩码单元 (如
FXR1[31:16]
) 的对应位 =1
,则接收报文的该位必须等于 模板单元 (如FXR1[15:0]
) 的对应位。 - 如果掩码单元的对应位 =
0
,则接收报文的该位可以是0
或1
(无关)。
- 如果掩码单元 (如
- 报文只需匹配任何一个屏蔽项 (
1A+1B
或2A+2B
),即可通过过滤器。
- 对于接收报文 (必须是标准格式
- 配置示例:在第一个屏蔽项 (
FXR1
) 中配置过滤所有0x1xx
标准数据帧:FXR1[15:0]
(模板 1B):STID[10:0]
=00100000000b
(0x100
),RTR=0
,IDE=0
。 (值 ≈0x2000
)。FXR1[31:16]
(掩码 1A):STID[10:8]
=111b
,STID[7:0]
=00000000b
,RTR
位掩码 =1
,IDE
位掩码 =1
。 (值 ≈0x1C00
)。EXID
掩码位写0
。
- 优缺点:允许一个过滤器定义两组独立的标准 ID 范围过滤规则。适用于需要过滤多组标准 ID 的场景。
总结与模式选择建议:
- 需要过滤少数 (1-4 个) 精确 ID:
- 只有标准 ID:优先使用 16 位列表模式 (一个过滤器管 4 个 ID)。
- 包含扩展 ID:使用 32 位列表模式 (一个过滤器管 2 个 ID)。
- 需要过滤一组或多组具有特定位特征的 ID (范围):
- 主要是标准 ID 范围:优先使用 16 位屏蔽模式 (一个过滤器管 2 组范围)。
- 需要过滤扩展 ID 范围或混合标准/扩展范围:使用 32 位屏蔽模式 (一个过滤器管 1 组范围)。
- 关键:项目规划 CAN ID 分配方案时,应尽量使同一类消息的 ID 具有固定的高位/位特征,以便高效利用屏蔽模式。避免 ID 随机分配导致只能使用低效的列表模式。
2.2.2 过滤器配置示例
场景一:
- 总线ID:
0x123
,0x234
,0x345
,0x456
,0x567
,0x678
(均为标准ID)。 - 目标接收ID:
0x234
,0x345
,0x567
(均为标准ID)。
配置方案:
- 选择位宽: 目标ID均为标准ID,优先选用16位位宽以最大化利用资源。
- 选择模式: 观察目标ID (
0x234
,0x345
,0x567
),它们之间没有明显的共同规律,无法使用屏蔽模式分组过滤,因此必须选择列表模式 (List Mode)。 - 配置寄存器:
- 在16位列表模式下,过滤器寄存器
r1
(低16位) 和r2
(高16位) 共可容纳4个ID值。 - 将目标ID写入对应的寄存器位置:
r1
低16位:写入0x234 << 5
。- 移位原因: CAN标准ID寄存器映射是左对齐的,而赋值通常是右对齐。标准ID (STID) 占据11位,其后有RTR位 (1位) 和IDE位 (1位),以及扩展ID保留位 (3位),总计需要左移5位才能正确对齐。低位移出的5位默认补0(RTR=0:数据帧;IDE=0:标准帧)。
- 如需接收远程帧:
0x234<<5 | 0x10
(即设置RTR位为1)。
r1
高16位:写入下一个目标ID0x345 << 5
。r2
低16位:写入目标ID0x567 << 5
。r2
高16位:由于只需3个ID,第4个位置可写入0
。- 注意: 此配置隐含要求总线上不存在ID为
0x000
的帧。
- 注意: 此配置隐含要求总线上不存在ID为
- 当前需求仅需3个ID,一个过滤器足够。若需过滤5个或更多ID,则需配置更多过滤器(系统共提供14个可用过滤器)。
- 在16位列表模式下,过滤器寄存器
场景二:
- 总线ID: 多组ID:
0x100
-0x1FF
(256个ID)0x200
-0x2FF
(256个ID)0x310
-0x31F
(16个ID)0x320
-0x32F
(16个ID)
- 目标接收ID:
0x200
-0x2FF
(256个ID) 和0x320
-0x32F
(16个ID) (均为标准ID)。
配置方案:
- 选择位宽: 目标ID均为标准ID,选用16位位宽。
- 选择模式: 目标ID数量众多(超过270个),列表模式无法容纳,必须使用屏蔽模式 (Mask Mode)。目标ID组 (
0x2xx
,0x32x
) 的设计符合屏蔽模式要求(高位固定,低位可变)。 - 配置寄存器 (16位屏蔽模式):
r1
低16位:存放ID值。r1
高16位:存放对应的屏蔽位/掩码值。r2
低16位:存放ID值。r2
高16位:存放对应的屏蔽位/掩码值。- 配置组1 (接收
0x200
-0x2FF
):r1
低16位 (ID): 写入0x200 << 5
(关键高位0x2
,低位默认0;移位5位对齐,RTR=0, IDE=0)。r1
高16位 (Mask): 写入0x700 << 5
(或0xF00 << 5
效果相同:0x700换算成二进制是0111 0000 0000,0xF00二进制是1111 0000 0000,再左移五位空出来RTR,IDE,EXID,0X700就变成了1110 0000 0000 0000)。- 掩码含义:
0x700
(二进制0111 0000 0000
) 左移5位后,高3位 (对应ID的0x2
) 要求必须匹配 (mask=1
),低8位 (对应ID的低8位) 不要求匹配 (mask=0
),允许任意值通过。这正好过滤出0x2xx
。 - RTR/IDE处理:
- ID部分默认RTR=0 (数据帧)。
- 如需接收远程帧,ID部分应
OR 0x10
(设置RTR=1)。 - 如需同时接收数据帧和远程帧,屏蔽位Mask的RTR位应设为
0
(不检查)。 - 屏蔽位Mask
OR 0x8
(IDE位掩码设为1),强制只接收标准帧 (IDE=0),避免误收扩展ID帧。
- 掩码含义:
- 配置组2 (接收
0x320
-0x32F
):r2
低16位 (ID): 写入0x320 << 5
(关键高位0x32
,低位默认0;移位5位对齐,RTR=0, IDE=0)。r2
高16位 (Mask): 写入0x7F0 << 5
。- 掩码含义:
0x7F0
(二进制0111 1111 0000
) 左移5位后,高7位 (对应ID的0x32
) 要求必须匹配 (mask=1
),低4位 (对应ID的低4位) 不要求匹配 (mask=0
),允许任意值通过。这正好过滤出0x32x
(16个ID)。 - RTR/IDE处理: 屏蔽位Mask
OR 0x8
(IDE位掩码=1) 确保只接收标准帧。RTR掩码设为1表示必须匹配ID中设定的RTR值 (此处为0,数据帧)。
- 掩码含义:
- 一个过滤器 (使用
r1
和r2
) 可过滤两组ID。如需过滤更多组ID,配置其他过滤器即可。
场景三:
- 总线ID:
0x123
(标准),0x234
(标准),0x345
(标准),0x56
(标准),0x12345678
(扩展),0x0789ABCD
(扩展)。 - 目标接收ID:
0x123
(标准) 和0x12345678
(扩展)。
配置方案:
- 选择位宽: 目标ID包含扩展ID (
0x12345678
),必须使用32位位宽。 - 选择模式: 两个目标ID无共同规律,无法分组,必须使用列表模式 (List Mode)。32位列表模式下,
r1
和r2
各可存放一个完整的32位ID配置项。 - 配置寄存器:
r1
(存放标准ID0x123
的配置):- 写入
0x123 << 21
。- 移位原因: CAN标准ID在32位映射图中占据高11位 (STID[10:0]),其后有RTR位 (1位), IDE位 (1位), 扩展ID保留位 (18位) 及控制位 (3位),总计需要左移21位才能将11位STID对齐到最高位。低位移出位默认补0 (RTR=0:数据帧;IDE=0:标准帧)。
- 如需接收远程帧:
OR 0x2
(设置RTR位为1,该位在映射图中是倒数第2位)。
- 写入
r2
(存放扩展ID0x12345678
的配置):- 写入
(0x12345678 << 3) | 0x4
。- 移位原因: CAN扩展ID在32位映射图中占据高29位 (ExtID[28:0]),其后是IDE位 (1位), 保留位 (1位), RTR位 (1位)。需要左移3位将29位ExtID对齐到最高位。
- 设置IDE位:
OR 0x4
(IDE=1,表示扩展帧,该位是倒数第3位)。 - 如需接收远程帧: 额外
OR 0x2
(设置RTR=1)。
- 写入
场景四:
- 总线ID:
0x12345600
-0x123456FF
(256个扩展ID) 和0x0789AB00
-0x0789ABFF
(256个扩展ID)。 - 目标接收ID:
0x12345600
-0x123456FF
(扩展ID)。
配置方案:
- 选择位宽: 目标ID为扩展ID,必须使用32位位宽。
- 选择模式: 目标ID数量大 (256个) 且具有高位固定、低位可变的特征,适合使用屏蔽模式 (Mask Mode)。
- 配置寄存器 (32位屏蔽模式):
r1
:存放ID值。r2
:存放对应的屏蔽位/掩码值。- 配置:
r1
(ID): 写入(0x12345600 << 3) | 0x4
(关键高位0x123456
,低8位默认0;移位3位对齐;OR 0x4
设置IDE=1 (扩展帧);RTR默认0 (数据帧))。r2
(Mask): 写入(0x1FFF00 << 3) | 0x4
(或| 0x6
如需同时匹配RTR)。- 掩码含义:
0x1FFF00
(二进制0001 1111 1111 1111 0000 0000
) 左移3位后,高13位 (对应ExtID的高13位0x1234
和0x56
的高5位) 要求必须匹配 (mask=1
),低8位 (对应ExtID的低8位) 不要求匹配 (mask=0
),允许任意值通过。这正好过滤出0x123456xx
。 - IDE/RTR处理:
| 0x4
将掩码的IDE位设为1
,表示必须匹配ID中的IDE=1 (扩展帧)。| 0x2
将掩码的RTR位设为1
,表示必须匹配ID中的RTR=0 (数据帧)。若需同时接收远程帧,此处RTR掩码应设为0
。
- 掩码含义:
常用特殊配置:
仅接收远程帧 (RTR Frames Only):
- 模式: 32位屏蔽模式。
- 配置:
r1
(ID):0x2
(仅设置RTR位=1)。r2
(Mask):0x2
(仅RTR位掩码=1,要求匹配RTR=1;其他位掩码=0,不检查)。
- 效果: 接收任何ID,但仅限远程帧类型。
全通模式 (Accept All):
- 模式: 32位屏蔽模式。
- 配置:
r1
(ID): 任意值 (通常用0
)。r2
(Mask):0x0
(所有位掩码=0,表示所有位都不需要匹配)。
- 效果: 接收总线上的所有报文 (任何ID,任何帧类型)。此配置在初始总线调试时非常有用。
总结:
CAN过滤器的配置需要根据具体的应用场景灵活选择位宽(16位或32位,由目标ID是否包含扩展ID决定)和模式(列表模式或屏蔽模式)。配置寄存器时,必须仔细参照寄存器映射图,正确处理ID值的移位操作(左移5位或21位用于16位模式的标准ID,左移3位用于32位模式的扩展ID)以及RTR位和IDE位的设置(通过 OR
操作)。屏蔽模式需要精心设计ID和掩码值以实现分组过滤。过滤器设计相对复杂,务必细心谨慎。
疑惑点:为什么16位列表模式中,标准ID需左移5位?
假设目标ID: 0x234
(标准ID,十六进制)
其二进制值: 10 0011 0100
(共11位,补足前导0为 0010 0011 0100
)
1. CAN寄存器的硬件映射规则(核心!)
- CAN标准帧的 接收过滤器寄存器 是 左对齐 的。
- 它的32位结构如下(以16位模式中的单个过滤器寄存器为例):
| 31-16 | 15-0 | ← 寄存器分高低16位 | STID[10:0] | RTR | IDE | EXID[17:13] | ← 实际有效位 (共16位)
STID[10:0]
:11位 标准ID(必须放在最高位!)RTR
:1位 (远程帧标志)IDE
:1位 (标准帧=0/扩展帧=1)EXID[17:13]
:3位 保留位(扩展ID片段,标准帧中无用)
2. 赋值时的矛盾点
- 当我们写代码时,赋值默认是 右对齐 的:
寄存器 = 0x234
→ 二进制0000 0010 0011 0100
(16位) - 但硬件要求STID必须左对齐!
直接赋值会导致ID错位:我们希望的布局: [STID][RTR][IDE][保留位] | 0010 0011 0100 | 0 | 0 | 000 | ← 正确! 实际赋值布局: [低位无用][STID片段][RTR][IDE] | 0000 0010 | 0011 0100 0 | 0 | 000 | ← 完全错误!
- ID被截断为
0011 0100
(仅8位),且高位被无用数据占据。
- ID被截断为
3. 左移5位的数学本质
- 左移5位 = 乘以32
0x234 << 5 = 0x234 * 32 = 0x4680
- 二进制视角:
此时值变为0x234 原始二进制: 0010 0011 0100 左移5位后: 0010 0011 0100 00000 ← 右侧补5个0
0010 0011 0100 0000
(即0x4680
)
4. 对齐后的寄存器布局
| 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 | ← 位序号
|----------------STID[10:0]------------|RTR|IDE|-保留位-|
| 0 1 0 0 0 1 1 0 1 0 0 0 0 0 0 0 | ← 0x4680的二进制
- 分解验证:
STID[10:0] = 0100 0110 100
→ 0100 0110 100 =0x234
(正确对齐到高11位!)RTR = 0
(数据帧)IDE = 0
(标准帧)保留位 = 000
(默认0)
关键总结
操作 | 数值 | 寄存器效果 |
---|---|---|
直接赋值 | 0x234 |
ID错位 → 过滤器失效 |
左移5位 | 0x4680 |
ID正确顶格对齐,RTR/IDE/保留位自动补0 |
✅ 为什么是5位?
保留位 (3位) + IDE (1位) + RTR (1位) = 5位
移位后,这5个低位正好容纳帧控制标志(全0即默认接收数据帧+标准帧)。
实战配置步骤
若要接收 0x234
的远程帧,只需:
uint32_t filter_value = (0x234 << 5) | 0x10; // 0x4680 | 0x10 = 0x4690
- 0x10的二进制:
0001 0000
→ 设置 RTR=1 (远程帧) - 此时寄存器值
0x4690
对应:| STID=0x234 | RTR=1 | IDE=0 | 保留位=000 |
💡 重要提示:扩展帧的移位原理相同(左移3位),区别在于IDE=1且保留位结构不同。理解这个对齐逻辑后,所有移位问题都会迎刃而解。
2.2.3 测试模式
接下来我们看一下测试模式 (Test Modes)。顾名思义,测试模式主要用于开发和调试阶段,便于进行自检和总线分析。CAN外设通常支持三种测试模式:静默模式 (Silent Mode)、环回模式 (Loopback Mode) 和环回静默模式 (Loopback Silent Mode)。这些模式在调试程序时非常有用,尤其是在需要同时验证发送和接收功能的情况下。
为何需要测试模式?
当调试基于CAN总线的系统(如CAN总线节点或无线收发模块)时,开发者需要同时编写发送和接收程序。如果数据未能正确接收,问题可能出在发送程序、接收程序或物理连接(如接线错误)上,定位故障点非常困难。
测试模式的核心价值在于支持自发自收测试 (Self-Transmit and Self-Receive Test):
- 开发者可以先在一个设备上配置测试模式,让该设备自己发送报文并自己接收。
- 当自发自收测试成功(即设备能正确接收自己发出的报文),说明该设备的发送功能、接收功能及内部逻辑基本正常。
- 确认单个设备工作正常后,再进行设备间的互联通信测试。
这种“先自测,再互联”的分步调试策略,能显著提高开发效率和系统健壮性。我们在后续代码实践中也将遵循此原则:先进行自发自收测试,成功后再进行多设备通信。
三种测试模式详解:
下图展示了CAN外设在正常模式和三种测试模式下的内部连接差异(假设框内为CAN外设,TX和RX为外部引脚):
[示意图概念:一个方框代表CAN外设,左侧有TX引脚,右侧有RX引脚]
静默模式 (Silent Mode):
- 目的: 分析CAN总线活动,自身不主动驱动总线电平,避免干扰总线。
- 内部连接变化:
- 发送器输出(TX Logic)被强制置为逻辑‘1’(隐性电平),相当于不主动发送任何显性位。
- 发送器输出内部连接到接收器输入(RX Logic)。
- 外部RX引脚依然连接接收器输入,可以接收总线上的报文。
- 功能:
- 自发自收: 设备发送的报文会被自身接收器接收(通过内部回路)。
- 总线监听: 同时,设备也能通过RX引脚接收总线上的其他报文。
- 典型应用: 构建CAN总线分析仪(Sniffer)。设备可以“安静地”监听总线上的所有通信(包括自身发送的测试报文),而不会向总线输出任何驱动电平,确保不影响总线原有通信。
环回模式 (Loopback Mode):
- 目的: 进行设备自测试,同时允许在TX引脚上观测实际发送的电平波形。
- 内部连接变化:
- 发送器输出(TX Logic)内部连接到接收器输入(RX Logic)。
- 发送器输出同时连接到外部TX引脚,可以驱动总线或供示波器等设备测量。
- 外部RX引脚被断开/隔离,设备无法接收来自总线的任何报文。
- 功能:
- 自发自收: 设备发送的报文会被自身接收器接收(通过内部回路)。
- 波形观测: 发送的报文电平波形会真实地出现在TX引脚上,方便进行物理层信号测量。
- 注意: 此处的“自发自收”发生在报文层面(即发送的完整CAN报文帧能被接收FIFO捕获),而非仅指底层电信号的回环。我们后续的代码示例将使用此模式进行自发自收验证。
环回静默模式 (Loopback Silent Mode):
- 目的: 进行严格的设备自测试(热自检),完全隔离于外部总线,互不影响。
- 内部连接变化:
- 发送器输出(TX Logic)内部连接到接收器输入(RX Logic)。
- 外部TX引脚被强制置为逻辑‘1’(隐性电平),不驱动总线。
- 外部RX引脚被断开/隔离。
- 功能:
- 纯粹的自发自收: 设备发送的报文仅被自身接收器接收(通过内部回路)。
- 完全隔离: 设备既不向总线发送有效电平(TX恒为隐性),也不接收总线上的任何报文(RX断开)。
- 典型应用(热自检 - Hot Self-Test): 设备上电后,在加入总线通信前进行自我检查。例如,设备可以发送一个测试报文,验证自身是否能正确接收。由于该模式将设备与物理总线完全隔离,因此:
- 不影响总线: 不会干扰总线上其他设备的正常通信。
- 不受总线影响: 不会被总线上的其他报文干扰自检过程。自检通过后,设备再切换到正常模式加入总线通信。
总结与优势:
这三种测试模式为CAN设备的开发和调试提供了强大的灵活性:
- 静默模式: 监听总线 + 自发自收(不影响总线)。
- 环回模式: 自发自收 + 发送波形观测(用于设备自测)。
- 环回静默模式: 纯粹自发自收 + 完全电气隔离(用于热自检)。
最关键的优势在于: 这些模式的切换仅需通过软件配置寄存器即可完成,无需改动任何物理接线,极大地方便了开发调试过程。
2.2.4 工作模式
接下来我们探讨CAN控制器的工作模式 (Operating Modes)。CAN外设主要支持三种核心工作模式:初始化模式 (Initialization Mode)、正常模式 (Normal Mode) 和睡眠模式 (Sleep Mode)。从名称即可大致理解其用途,下面进行详细说明。
初始化模式 (Initialization Mode):
- 目的: 禁止报文的接收和发送,专用于配置CAN外设的寄存器。
- 必要性: 在正常模式下修改配置参数是危险的。参数配置过程中(尚未完成),CAN外设可能基于不完整或不正确的配置开始工作,这极易导致总线错误或干扰其他节点通信。
- 操作流程:
- 在修改任何关键参数(如波特率、过滤器设置、模式切换)前,必须先将CAN外设置于初始化模式。
- 完成所有必要配置后,再切换到正常模式。
- 核心作用: 确保配置过程安全、可靠,避免在初始化阶段干扰CAN总线。
正常模式 (Normal Mode):
- 目的: CAN外设的标准工作状态,用于正常接收和发送CAN报文。
- 操作: 在初始化模式下完成配置后,即可切换到正常模式开始通信。
- 特点: 这是CAN节点参与总线通信时必须处于的模式。
睡眠模式 (Sleep Mode):
- 目的: 实现低功耗运行。在此模式下,CAN外设的核心功能(如收发器时钟)大部分停止工作,显著降低功耗。
- 唤醒机制:
- 软件唤醒 (Software Wake-up): 通过程序(设置寄存器)主动将CAN外设切换回正常模式。
- 硬件自动唤醒 (Automatic Wake-up): 当CAN外设检测到总线出现活动(例如有报文开始传输)时,自动退出睡眠模式并准备接收报文。
- 自动唤醒配置:
- 通过配置 AWUM (Automatic Wake-up Mode) 寄存器位启用或禁用此功能:
AWUM = 1
: 启用自动唤醒。检测到总线活动时,硬件自动清除SLEEP
状态,唤醒外设。AWUM = 0
: 禁用自动唤醒。只能通过软件唤醒。
- 通过配置 AWUM (Automatic Wake-up Mode) 寄存器位启用或禁用此功能:
- 应用场景:
- 启用自动唤醒 (
AWUM=1
): 在低功耗应用中非常有用。节点处理完数据后,可“无脑”进入睡眠模式。一旦总线有活动,它能零延迟自动唤醒接收报文,实现功耗节省与通信实时性的完美平衡。 - 禁用自动唤醒 (
AWUM=0
): 仅需软件唤醒。适用于对功耗不敏感或唤醒时机由应用严格控制的场景。 - 若无特殊功耗要求,节点可一直工作在正常模式。
- 启用自动唤醒 (
工作模式状态与切换:
CAN外设的工作模式通过特定的状态位 (Status Bits) 和请求位 (Request Bits) 来管理和确认。
状态位 (反映当前实际状态):
- SLAK (Sleep Acknowledge):
SLAK = 1
: 硬件已确认进入睡眠模式。SLAK = 0
: 硬件未处于睡眠模式 (可能在正常或初始化模式)。
- INAK (Initialization Acknowledge):
INAK = 1
: 硬件已确认进入初始化模式。INAK = 0
: 硬件未处于初始化模式 (可能在正常或睡眠模式)。
- 正常模式状态:
SLAK = 0
且INAK = 0
。
- SLAK (Sleep Acknowledge):
请求位 (用于发起模式切换):
- SLEEP (Sleep Request):
SLEEP = 1
: 请求进入睡眠模式。SLEEP = 0
: 请求退出睡眠模式 (唤醒)。
- INRQ (Initialization Request):
INRQ = 1
: 请求进入初始化模式。INRQ = 0
: 请求退出初始化模式 (进入正常模式)。
- SLEEP (Sleep Request):
复位后的默认状态: 通常为睡眠模式 (
SLAK = 1
,INAK = 0
)。模式切换流程 (关键点):
- 请求位 (
SLEEP
,INRQ
) 的配置仅发出请求,不代表立即生效。硬件需要时间完成必要的状态迁移。 - 进入睡眠 (
SLEEP=1
): 硬件在安全停止当前活动(如完成正在发送的报文)后,才会真正进入睡眠并设置SLAK=1
进行确认。 - 进入正常模式 (
INRQ=0
或SLEEP=0
): 硬件必须等待总线空闲 (Bus Idle
) 才会执行切换并清除INAK
或SLAK
。这是为了防止在总线活动期间切换模式导致通信错误或冲突。 - 状态确认: 软件应通过检查
SLAK
和INAK
状态位来确认模式切换是否真正完成。
- 请求位 (
总结:
理解CAN工作模式及其切换机制至关重要:
- 初始化模式是安全配置的保障。
- 正常模式是通信的基础。
- 睡眠模式是实现低功耗的关键,其自动唤醒 (
AWUM=1
) 功能在需要兼顾功耗和响应性的应用中极具价值。 - 模式切换是一个请求-确认的过程,需关注状态位 (
SLAK
,INAK
) 的变化,并理解总线空闲是进入正常模式的前提条件。
2.2.5 位时间特性
位时序决定了CAN总线上每个位的采样点位置 (Sampling Point) 和位持续时间 (Bit Duration),而后者直接决定了通信的波特率 (Baud Rate)。
位时序结构:STM32 vs. CAN标准协议
标准CAN协议 (ISO 11898-1):
- 一个位时间划分为四个段 (Segments):
- 同步段 (Synchronization Segment, SS): 固定为 1 TQ (Time Quantum)。用于总线边沿同步。
- 传播时间段 (Propagation Time Segment, PTS): 可配置若干TQ。用于补偿信号在总线上的物理传播延迟。
- 相位缓冲段1 (Phase Buffer Segment 1, PBS1): 可配置若干TQ。用于补偿节点时钟误差。
- 相位缓冲段2 (Phase Buffer Segment 2, PBS2): 可配置若干TQ。用于补偿节点时钟误差。
- 采样点 (Sampling Point): 位于 PBS1 段和 PBS2 段之间。
- 一个位时间划分为四个段 (Segments):
STM32 CAN外设的实现:
- STM32的设计者将标准协议中的 PTS 和 PBS1 两个段合并为一个段。
- 因此,STM32的位时间只包含三个段:
- 同步段 (SS): 固定为 1 TQ。
- 时间段1 (BS1 - Bit Segment 1): 可配置 1 至 16 TQ。对应标准协议的 PTS + PBS1。
- 时间段2 (BS2 - Bit Segment 2): 可配置 1 至 8 TQ。对应标准协议的 PBS2。
- 再同步跳转宽度 (SJW - Resynchronization Jump Width): 可配置 1 至 4 TQ。用于限制在再同步时相位缓冲段可以调整的最大TQ数。
- 采样点 (Sampling Point): 位于 BS1 段和 BS2 段之间(即BS1结束处)。
- 核心差异: 仅在于将PTS和PBS1合并为BS1段,采样点位置定义和BS2段配置与标准协议一致。这种合并简化了配置参数(少一个段需要设置),同时保持了与标准协议的兼容性。
波特率计算 (Bit Rate Calculation):
波特率是单位时间内传输的位数,等于位时间的倒数。计算公式如下:
位时间 (Bit Time, T_bit):
T_bit = (1 + TS1 + TS2) * T_tq
- 其中:
TS1
: BS1段配置寄存器值 (范围 0-15)。实际BS1段长度 = TS1 + 1 TQ。TS2
: BS2段配置寄存器值 (范围 0-7)。实际BS2段长度 = TS2 + 1 TQ。T_tq
: 一个时间量子 (Time Quantum) 的持续时间。
时间量子 (T_tq):
T_tq = (BRP + 1) * T_pclk
- 其中:
BRP
: 波特率预分频器寄存器值 (范围 0-1023)。T_pclk
: APB1总线时钟周期。- 对于STM32F1系列(如C8T6),CAN外设通常挂载在APB1总线上。如果APB1时钟频率
F_pclk1 = 36 MHz
,则T_pclk = 1 / 36,000,000 秒
。
波特率 (Bit Rate):
Bit Rate = 1 / T_bit = F_pclk1 / [(BRP + 1) * (1 + TS1 + TS2)]
- 简化理解:
- APB1时钟 (
F_pclk1
) 首先经过(BRP + 1)
分频,得到 TQ时钟频率 (F_tq
):F_tq = F_pclk1 / (BRP + 1)
- 每个位包含
(1 + TS1 + TS2)
个 TQ。 - 因此,波特率
= F_tq / (1 + TS1 + TS2) = F_pclk1 / [(BRP + 1) * (1 + TS1 + TS2)]
- APB1时钟 (
配置示例 (以STM32F103C8T6为例):
- 目标波特率:
125 kbps
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;//重新同步跳跃宽度1个时间单位
CAN_InitStructure.CAN_BS1=CAN_BS1_3tq;//时间段1为3个时间单位
CAN_InitStructure.CAN_BS2=CAN_BS2_2tq;//时间段2为2个时间单位
CAN_InitStructure.CAN_Prescaler=24;//时间单位长度为24 250k
//波特率为:36M/24(1+3+2)=0.25 即250K
2.2.6 中断
1. 中断 (Interrupts)
当CAN总线内部发生重要事件时,中断机制允许程序自动暂停当前任务,跳转执行特定的中断服务函数 (ISR),以便及时处理事件。STM32 CAN外设提供了丰富的中断源,并独占四个专用的NVIC中断向量(即对应四个独立的中断服务函数)。
主要中断源与对应的中断函数:
发送中断 (Transmit Interrupt):
- 触发条件: 当发送邮箱 (Transmit Mailbox) 从非空状态变为空状态(即报文已成功发送出去)时触发。
- 应用场景: 在ISR中可加载新的报文到空闲的发送邮箱,实现连续发送或发送状态监控。
FIFO 0 中断 (FIFO 0 Interrupt):
- 触发条件:
- 接收到新报文: 当FIFO 0接收到一个报文(
FMP0 > 0
)。 - FIFO 满 (Full): FIFO 0已满 (
FULL0 = 1
)。 - FIFO 溢出 (Overrun): FIFO 0已满时又收到新报文,导致报文丢失 (
FOVR0 = 1
)。
- 接收到新报文: 当FIFO 0接收到一个报文(
- 应用场景: 在ISR中及时处理接收到的报文,避免FIFO满或溢出丢失数据。
- 触发条件:
FIFO 1 中断 (FIFO 1 Interrupt):
- 触发条件: 与FIFO 0中断类似,但针对FIFO 1:
- 接收到新报文 (
FMP1 > 0
)。 - FIFO 1满 (
FULL1 = 1
)。 - FIFO 1溢出 (
FOVR1 = 1
)。
- 接收到新报文 (
- 应用场景: 与FIFO 0中断相同,用于处理FIFO 1的接收事件。
- 触发条件: 与FIFO 0中断类似,但针对FIFO 1:
状态改变/错误中断 (Status Change/Error Interrupt):
- 触发条件: 当CAN外设状态发生重要变化或检测到错误时触发:
- 发生错误 (Error) (如位错误、格式错误、ACK错误、CRC错误等)。
- 成功唤醒 (Wake-up) 退出睡眠模式。
- 成功进入睡眠模式 (Sleep Mode Entry)。
- 其他状态变化(如总线关闭(Bus-Off)状态进入/退出)。
- 应用场景: 在ISR中进行错误处理、状态监控、唤醒后初始化等操作。
- 触发条件: 当CAN外设状态发生重要变化或检测到错误时触发:
中断架构优势:
- 独立处理: 四种类型的事件(发送完成、FIFO0接收事件、FIFO1接收事件、状态/错误)拥有各自独立的中断服务函数 (ISR)。这允许开发者对不同事件编写专用的处理逻辑。
- 优先级灵活: 通过NVIC (Nested Vectored Interrupt Controller),可以为这四个中断源配置不同的优先级 (Priority) 和子优先级 (Subpriority)。例如,可以赋予错误中断最高优先级,确保关键错误被及时响应。
中断信号流向 (图解说明 - 概念简化):
- 事件发生 (Event Occurrence): CAN外设内部硬件检测到事件(如发送邮箱空、FIFO收到报文、发生错误等)。
- 标志位置位 (Flag Setting): 对应的事件标志位会被硬件自动置位 (
=1
)。例如:- 发送邮箱0空 →
TME0 (Transmit Mailbox 0 Empty)
或RQCP0 (Request Completed Mailbox 0)
置1。 - FIFO 0 收到新报文 →
FMP0 (FIFO 0 Message Pending)
不再是0。 - FIFO 0 满 →
FULL0
置1。 - FIFO 0 溢出 →
FOVR0
置1。 - 发生错误 →
ERR
(或更具体的错误标志位如BOFF
,EPVF
,EWGF
) 置1。 - 唤醒 →
WKUI (Wake-up Interrupt)
置1。 - 进入睡眠 →
SLAKI (Sleep Acknowledge Interrupt)
置1。
- 发送邮箱0空 →
- 中断使能 (Interrupt Enable): 每个中断源都有一个对应的中断使能寄存器位 (Interrupt Enable Bit,
xxx_IE
) (例如TMEIE
,FMPIE0
,ERRIE
)。仅当该使能位被软件置为1
时,对应的事件标志位信号才能通过后续的逻辑门。 - 信号门控 (Gating - AND Gate): 事件标志位信号 (
Flag
) 和中断使能位信号 (IE
) 输入到一个逻辑与门 (AND Gate)。只有当Flag = 1
且IE = 1
时,该与门的输出才为1
(有效中断请求信号)。 - 信号汇聚 (Aggregation - OR Gate): 所有类型(发送、FIFO0、FIFO1、状态/错误)的有效中断请求信号 (
=1
) 输入到一个逻辑或门 (OR Gate)。只要其中任意一个输入为1
,该或门的输出就为1
。 - NVIC 中断请求 (NVIC Interrupt Request): 或门的输出连接到NVIC。对于STM32 CAN外设,NVIC中有四个独立的输入通道对应上述四种中断类型。当一个通道收到
1
(有效请求) 时:- NVIC 根据配置的优先级决定是否挂起该中断。
- 当优先级允许时,CPU 暂停当前任务,跳转执行对应的中断服务函数 (ISR)。
- 中断服务函数 (ISR): 在 ISR 中,软件需要:
- 检查标志位: 确定具体是哪个事件触发了中断(因为同一中断向量下可能有多个标志位)。
- 执行处理逻辑: 如读取接收FIFO、填充发送邮箱、处理错误状态等。
- 清除标志位 (重要!): 在处理完成后,必须通过软件清除触发该中断的事件标志位。否则,该中断会持续触发(不断进入ISR)。
2.2.6 时间触发通信(了解)
时间触发通信 (Time Triggered Communication - TTC)
- 概念: 此功能基于 ISO 11898-4 协议(CAN的高层协议),旨在实现全局时间同步和确定性调度。
- 核心思想: 网络中的所有节点基于一个全局同步时钟。每个节点只能在预先分配好的、固定的时间槽 (Time Slot) 内发送其特定的报文。这避免了传统CAN基于标识符(ID)的仲裁 (Arbitration) 机制。
- 优势: 提供严格的消息传输延迟保证,非常适合需要高确定性的实时控制系统(如X-by-Wire)。
- 现状: 在现阶段的学习和应用中(尤其是基础CAN通信),可以将其视为一个高级的、可选的功能模块进行了解。STM32 CAN外设硬件支持是实现TTC的基础之一,但完整的实现需要复杂的协议栈支持。对于大多数应用,掌握基于仲裁的标准CAN通信即可。
STM32 CAN 时间触发通信 (TTC) 硬件设计简述
1. 核心组件:16位自由运行计数器
- CAN外设内部集成一个16位自由运行计数器 (Free-Running Counter)。
- 当TTCM (Time Triggered Communication Mode) 控制位置
1
(开启TTC功能)时:- 该计数器在每一个CAN位时间 (Bit Time) 结束时自动加1。
- 计数器从
0
开始计数,计到最大值65535 (0xFFFF)
后溢出,自动归零,并继续循环计数。
- 计数器频率 = CAN波特率。例如:
- 波特率为
1 Mbps
(位时间1 µs
) → 计数器每1 µs
加1。 - 波特率为
500 kbps
(位时间2 µs
) → 计数器每2 µs
加1。
- 波特率为
- 作用: 该计数器的值称为时间戳 (Timestamp),用于标记事件发生的相对时间点。
2. 时间戳捕获机制
- 发送邮箱 (Transmit Mailbox):
- 每个发送邮箱都有一个关联的
TIME
寄存器。 - 当硬件开始发送一个报文的帧起始 (SOF - Start of Frame) 位时:
- 当前计数器的值会被硬件自动捕获 (Capture) 并存入该邮箱对应的
TIME
寄存器。
- 当前计数器的值会被硬件自动捕获 (Capture) 并存入该邮箱对应的
- 每个发送邮箱都有一个关联的
- 接收 FIFO (Receive FIFO):
- 每个接收FIFO槽位(存储接收到的报文)也有一个关联的
TIME
寄存器。 - 当硬件成功接收到一个报文的 帧起始 (SOF) 位时:
- 当前计数器的值会被硬件自动捕获并存入该接收报文对应的
TIME
寄存器。
- 当前计数器的值会被硬件自动捕获并存入该接收报文对应的
- 每个接收FIFO槽位(存储接收到的报文)也有一个关联的
- 作用: 这样,每个发送出去和接收进来的报文,其开始传输/接收的精确时刻(相对于内部计数器)都被记录下来。
3. 发送时间戳广播 (可选功能 - TGT)
- TGT (Transmit Global Time) 功能: 可通过配置开启(通常与TTCM一起启用)。
- 功能描述:
- 当开启TGT功能后,在发送一个报文的帧起始 (SOF) 位时:
- 计数器的值被捕获存入发送邮箱的
TIME
寄存器(同上)。 - 硬件自动将这16位的时间戳值,复制到待发送报文数据段 (Data Field) 的最后两个字节。
- 计数器的值被捕获存入发送邮箱的
- 当开启TGT功能后,在发送一个报文的帧起始 (SOF) 位时:
- 关键要求:
- 使用此功能时,报文的
DLC
(Data Length Code) 必须设置为8
(即数据段长度为8字节)。 - 数据段的第7字节 (Byte 6) 和第8字节 (Byte 7) 会被时间戳占用,用户不能使用。
- 使用此功能时,报文的
- 作用: 发送节点不仅自己记录发送时间戳,还通过报文将其广播给总线上所有接收节点。这为全网络节点的时间同步提供了基础数据。
4. 时间戳存储格式 (重要澄清)
- 当时间戳值被捕获到
TIME
寄存器或插入数据段时:- 高位字节 (MSB) 存储在较高地址(例如数据段的 Byte 6)。
- 低位字节 (LSB) 存储在较低地址(例如数据段的 Byte 7)。
- (注意:部分中文手册此处描述可能有误,实际存储格式遵循上述规则,与图示一致)。
核心价值与应用场景:
- TTC硬件(计数器、捕获机制、TGT)为在CAN网络上实现精确的时间同步 (Time Synchronization) 和基于时间槽的确定性调度 (Time-Slotted Deterministic Scheduling) 提供了底层支持。
- 所有节点可以利用捕获到的时间戳(尤其是广播的发送时间戳)来校准本地时钟,实现全局时间一致。
- 节点可以在预先分配好的、确定的时间点发送报文,避免总线仲裁,保证关键报文在严格定义的时间窗口内传输。这对于需要高可靠性和严格实时性的系统(如汽车线控系统)至关重要。
2.2.7 错误处理和离线恢复
最后,我们简要介绍STM32 CAN的错误处理 (Error Handling) 和离线恢复 (Bus-Off Recovery) 机制,并概览参考手册的相关内容。
1. 错误处理与离线恢复
STM32 CAN的错误处理机制严格遵循ISO 11898-1 CAN协议标准,但也包含一个特有的配置选项。
- 核心组件:
- TEC (Transmit Error Counter) - 发送错误计数器: 记录发送相关的错误。
- REC (Reception Error Counter) - 接收错误计数器: 记录接收相关的错误。
- 计数器的增减规则与协议标准一致(详见之前讲解或协议文档)。
- 错误状态转换 (遵循协议标准):
- 主动错误状态 (Error Active): 默认状态。节点可正常发送报文,并在检测到错误时发送主动错误帧。
- 被动错误状态 (Error Passive): 当 TEC > 127 或 REC > 127 时进入。节点仍可通信,但发送错误帧变为被动形式(仅发送隐性位),且发送间隔增大。
- 离线状态 (Bus-Off): 当 TEC > 255 时进入。节点完全脱离总线,停止发送和接收报文(相当于被总线“踢出”)。
- 离线恢复过程 (遵循协议标准):
- 处于离线状态的节点,在检测到总线连续出现 128次隐性位 (128 occurrences of 11 recessive bits) 后,会自动尝试恢复。
- 恢复路径:离线状态 → 错误主动状态。
- STM32 个性化设计:ABOM (Automatic Bus-Off Management)
- 功能: 控制离线恢复过程是自动还是手动触发。
- 配置:
- ABOM = 1 (开启): 遵循协议标准。进入离线状态后,硬件自动开始监控总线上的128个隐性位,满足条件即自动恢复到错误主动状态。(推荐默认配置)
- ABOM = 0 (关闭): 进入离线状态后,不会自动开始恢复监控。
- 手动恢复流程 (当 ABOM = 0 时):
- 软件请求进入初始化模式 (设置
INRQ = 1
)。 - 软件请求退出初始化模式 (设置
INRQ = 0
)。这相当于对CAN控制器进行了一次软件复位。 - 在退出初始化模式后,硬件才开始监控总线上的128个隐性位。满足条件后,恢复到错误主动状态。
- 软件请求进入初始化模式 (设置
- 本质区别: ABOM 位相当于在协议规定的“自动恢复路径”上加了一个开关。
ABOM=1
时开关闭合,恢复自动进行;ABOM=0
时开关断开,需要软件干预(初始化模式切换)来“手动合闸”启动恢复监控。
2. STM32 CAN 参考手册 (RM0008 / RM0090 等) 导读
本章节内容主要对应于参考手册的 第22章:Controller area network (bxCAN)。
- 简介与网络拓扑: 概述CAN特性和基本网络结构。
- 整体框图 (Block Diagram): 提供外设高层级结构视图,可结合课程PPT中的结构图理解。
- 工作模式 (Operating Modes):
- 初始化模式 (Initialization mode)
- 正常模式 (Normal mode)
- 睡眠模式 (Sleep mode)
- 手册提供更详细的文字描述。
- 测试模式 (Test modes):
- 静默模式 (Silent mode)
- 环回模式 (Loopback mode)
- 环回静默模式 (Loopback combined with Silent mode)
- 发送处理 (Transmit processing):
- 发送优先级规则 (Mailbox priority)
- 发送中止 (Abort procedure)
- 禁止自动重传 (Disabling automatic retransmission -
NART
)
- 时间触发通信 (Time triggered communication mode - TTCM): 简要介绍该模式。
- 接收管理 (Receive management):
- 三级接收FIFO (3-level receive FIFO) 结构。
- FIFO溢出处理机制 (Overrun handling)。
- 标识符过滤 (Identifier filtering):
- 核心难点,包含:
- 模式选择:屏蔽位模式 (Mask mode) vs 列表模式 (List mode)。
- 位宽选择:16位 vs 32位。
- 应用场景分析。
- 过滤器匹配序号 (Filter match index): 标识报文匹配到的过滤器组号(非简单的过滤器编号,其编排规则见手册图表),有助于高效处理接收数据。
- 过滤器优先级规则 (Filter priority): 了解多个过滤器组间的优先级判定。
- 示例 (Filtering examples): 提供配置案例图示。
- 核心难点,包含:
- 报文存储 (Message storage): 描述报文在邮箱和FIFO中的存储格式。
- 出错管理 (Error management):
- 包含刚讨论的错误计数器、状态转换及 ABOM (Automatic bus-off management) 配置。
- 位时间特性 (Bit timing):
- 位时序段定义 (SS, BS1, BS2)。
- 波特率计算方法 (
BRP
,TS1
,TS2
)。
- 中断 (Interrupts):
- 明确 4个专用中断向量:发送、FIFO0、FIFO1、状态改变/错误。
- 寄存器描述 (Registers):
- 非常重要! 包含所有CAN控制/状态/配置寄存器的详细说明。
- 使用方法:
- 快速浏览寄存器列表,了解存在哪些寄存器。
- 在阅读手册前面章节或代码时,遇到大写字母的寄存器名称 (如
CAN_MCR
,CAN_MSR
,CAN_TSR
,CAN_ESR
,CAN_BTR
,CAN_IER
,CAN_FMR
等),即可在此部分搜索查阅其具体功能和每个位的含义(例如搜索INRQ
查看初始化请求位说明)。