【江科大CAN】2.1 STM32 CAN外设(上)

2.1 STM32 CAN外设(上)

      • 2.1.1 STM32 CAN外设简介
      • 2.1.2 外围电路设计
      • 2.1.3 STM32 CAN内部结构
      • 2.1.4 发送流程详解
      • 2.1.5 接收流程详解
      • 2.1.6 关键配置位总结

STM32 CAN外设讲解

大家好,欢迎继续观看CAN总线入门教程。本节开始,我们正式进入本套课程的第二部分:STM32 CAN外设的讲解。经过前面五个视频的学习,相信大家已经对CAN总线的基本知识有了扎实的理解 [修改] (更严谨,“了如指掌”略显绝对)。接下来,我们就在实践中验证所学的知识吧!

第二部分我们以STM32F103C8T6这款芯片为例,介绍其内部的CAN外设原理。学会了硬件原理,下一部分我们就可以写程序来解决实际项目的需求,完成从理论到实践的全过程

:本节课内容来源于STM32手册中对CAN外设的介绍。请打开资料链接(已更新部分资料):

  • 新增STM32相关资料:参考文档、部分程序源码。
  • 新增CAN收发器模块商家资料:参考文档、模块原理图、源代码(供参考)。

学习建议:学完视频后,请再详细查阅STM32F10xxx参考手册中文版中的第22章:控制器局域网 (bxCAN) 补充细节。

学习基础:后续内容需要STM32基础(了解基本概念、会编写下载程序、掌握GPIO输入输出、使用OLED调试工具)。相关基础可参考我之前的STM32入门教程。

2.1.1 STM32 CAN外设简介

在这里插入图片描述

  • 内置bxCAN外设:支持CAN 2.0ACAN 2.0B(即支持标准格式扩展格式)。
  • 功能核心:硬件自动完成CAN报文发送按照过滤器自动接收指定报文。程序只需处理报文数据,无需关注总线电平细节(帧格式、位同步、仲裁、错误处理等均由硬件完成),使用便捷。
  • 关键参数
    • 波特率:最高 1 Mbps(完美支持高速CAN)。
    • 发送:3个可配置优先级的发送邮箱(发送缓冲区)。
    • 接收:2个三级深度的接收FIFO(接收缓冲区,可缓存6个报文)。
    • 14个过滤器组(互联型有28个):用于按ID过滤接收报文(只接收需要的报文)。
  • 特色功能(了解即可):时间触发通信、自动离线恢复、自动唤醒、禁止自动重传、接收FIFO溢出方式可配置、发送优先级可配置、双CAN模式(互联型)等。
  • STM32F103C8T6资源:内置 CAN1(仅一个CAN外设)。

2.1.2 外围电路设计

在这里插入图片描述

  1. CAN拓扑结构

    • 节点 = CAN控制器 (STM32内部) + CAN收发器 (如TJA1050)。
    • STM32引脚:CAN_TX -> PA12, CAN_RX -> PA11
    • 注意:如果CAN与USB需要同时使用,需要将CAN引脚重映射到PB8和PB9 。
  2. 收发器电路
    在这里插入图片描述

    • 核心芯片:TJA1050
    • 关键连接:收发器 TXD -> STM32 CAN_TX (PA12), 收发器 RXD -> STM32 CAN_RX (PA11)
    • 供电:收发器 VCC 必须接5V(以满足总线电平规范)。
    • 终端电阻:总线物理两端各接一个120Ω电阻。实验模块自带120Ω电阻。
      • 实验说明:实验中(如三设备)未移除中间模块电阻(三个电阻)也能工作,但实际项目应严格按规范(仅保留总线物理两端的电阻)。
      • 如果正常使用下,多设备连接,只需在总线物理两端各保留一个电阻。
    • 模块附加电路:部分模块在 CAN_H/CAN_L 上串联10Ω电阻(抗噪)并接30pF电容(滤波),手册参考电路无此设计。

2.1.3 STM32 CAN内部结构

在这里插入图片描述
该框图可分为两个主要部分:

  1. 主 CAN (CAN1):位于框图上半部分。这是我们当前芯片 STM32F103C8T6 所拥有的唯一 CAN 外设资源,也是我们学习的核心。
  2. 从 CAN (CAN2):位于框图下半部分
    • 仅存在于互联型 (Connectivity Line) STM32 芯片中(如 STM32F107/STM32F105)。
    • STM32F103C8T6 属于基本型,没有 CAN2,因此这部分无需关注
    • 互联型芯片特性:在互联型芯片中,CAN1 和 CAN2 并非完全独立CAN2 主要作为 CAN1 的辅助两者共同管理同一个 CAN 总线。这种设计主要是为了分担负载或提供冗余等高级功能。此处仅作了解。

聚焦主 CAN (CAN1) 部分:
框图上半部分清晰地展示了 CAN1 的核心构成,主要分为三大功能模块

  1. CAN 2.0B 主动核心 (bxCAN Core - CAN 2.0B Active) - 左侧模块
    在这里插入图片描述

    • 这是 bxCAN 外设的“大脑”和“引擎”,包含了实现 CAN 2.0A/B 协议所需的全部核心逻辑电路(位定时、位填充/解填充、帧处理、仲裁、错误检测、ACK 处理、CRC 计算/校验等)。
    • 核心与程序的接口:核心内部包含大量控制寄存器、状态寄存器和数据寄存器
      • 程序通过读写这些寄存器配置 CAN 外设的工作模式、参数(如波特率)启动/停止操作查询状态(如发送/接收完成、错误标志)
      • 一句话总结程序通过读写寄存器来完全控制和监视硬件 CAN 电路的运行。这些寄存器的详细描述可在 STM32 参考手册的“CAN 寄存器描述”章节查阅。后续视频中遇到关键寄存器时,我们会直接解释其功能和用法。
  2. 发送邮箱 (Transmit Mailboxes) - 中间模块
    在这里插入图片描述

    • bxCAN 提供了 3 个独立的发送邮箱 (Mailbox 0, 1, 2)。
    • 功能:每个邮箱都是一个存储单元,用于临时存放一个完整的待发送 CAN 报文(包含帧信息:ID、RTR、IDE、DLC 以及 0-8 字节数据)。
    • 发送流程
      1. 程序选择一个空置的发送邮箱
      2. 将待发送报文的所有参数和数据写入该邮箱对应的寄存器。
      3. 设置该邮箱的 TXRQ (Transmit Request) 寄存器位为 1请求发送
    • 后续自动化:一旦请求发送被置位,后续所有操作均由硬件自动完成,程序无需干预:
      • 等待总线空闲 (Bus Idle)。
      • 执行位同步 (Bit Synchronization)。
      • 处理总线仲裁 (Arbitration)。
      • 操作 CAN_TX 引脚输出波形。
      • 执行位填充 (Bit Stuffing)。
      • 处理错误检测与恢复 (Error Handling)。
      • 等待/处理 ACK 槽。
      • 发送 EOF 等。
    • 设计目的:使用起来非常简单高效。程序只需“告诉”硬件发什么,硬件负责“搞定”整个发送过程。三个邮箱提供了发送缓冲,允许程序连续写入多个待发报文,硬件按策略依次发送,减少程序等待时间。
  3. 接收部分 (Receive Section) - 右侧模块
    在这里插入图片描述

    • 该部分包含两个关键子模块:标识符过滤器 (Identifier Filters)接收 FIFO (Receive FIFOs)
    • 基本接收流程
      • CAN 总线上出现一个数据帧或远程帧的报文波形时,bxCAN 核心硬件电路自动捕获并完整接收该报文。
      • 接收到的报文首先经过标识符过滤器组
        • 过滤器作用:程序可以预先在 14 个过滤器组配置过滤规则(例如,只接收特定 ID 范围的报文,或屏蔽某些 ID 的报文)。硬件会自动将接收到的报文 ID 与所有启用的过滤器规则进行比对
        • 过滤结果
          • 如果报文 ID 匹配任何一个启用的过滤器规则,则该报文被视为“需要的”,允许进入下一步。
          • 如果报文 ID 无法匹配任何一个启用的过滤器规则,则该报文直接被硬件丢弃(“扔掉”),不会通知程序。这极大地减轻了软件处理无关报文的负担
      • 通过过滤器的报文不会直接交给程序,而是存入接收 FIFO
    • 接收 FIFO (FIFO0 & FIFO1)
      • bxCAN 提供了 2 个独立的接收 FIFOFIFO0FIFO1
      • FIFO 含义First-In-First-Out,先进先出缓冲区队列。通俗地说,就是排队
      • 功能:每个 FIFO 相当于一个队列,队列深度为 3 个邮箱 (Mailbox)。也就是说,每个 FIFO 最多可以暂存 3 个通过过滤器的接收报文
      • 报文存储:通过过滤器的报文,会根据过滤器配置时指定的目标(由程序设定),自动进入 FIFO0 或 FIFO1 的队列末尾排队
      • 程序读取:程序通过读取 FIFO 对应的寄存器,可以从队列头部(最先进入的报文) 逐个读取报文数据和状态信息。读取后需要释放邮箱,腾出空间接收新报文。
      • 优势
        • 缓冲作用:如果 CAN 总线报文接收速度很快,而程序未能及时读取,报文可以在 FIFO 中排队等待
        • 避免丢失:FIFO 的缓冲能力(每个 FIFO 最多 3 个报文)在一定程度上避免了因程序处理不及时导致的报文丢失,非常实用。
      • 双 FIFO 设计目的:提供两个独立的接收队列。程序可以配置不同优先级的报文或不同类型的报文进入不同的 FIFO(例如,重要报文进 FIFO0,普通报文进 FIFO1)。这样,即使普通报文很多导致 FIFO1 排队甚至溢出,重要报文仍然可以在 FIFO0 中被及时接收和处理,降低了重要报文丢失的概率。

框图局限性
手册提供的框图清晰地展示了主要功能模块(核心、发送邮箱、接收过滤器/FIFO)及其连接关系,但对于发送邮箱的状态流转、过滤器具体工作模式、FIFO 队列管理细节等描绘得不够详尽。因此,在接下来的内容中,我们将通过更详细的流程图和文字描述来深入解析这些关键流程的细节。

核心框图可划分为:
STM32 CAN 外设核心流程详解 (发送与接收)

为了更清晰地理解 CAN 报文在 STM32 bxCAN 外设中的具体流转过程,我们聚焦于发送接收的核心流程。可以将 bxCAN 硬件逻辑视为一个强大的“管理员”。程序只需告诉它要发送什么报文,以及从它那里读取已接收且需要的报文,而总线操作的底层细节(等待空闲、波形输出、位同步、仲裁、错误处理等)均由管理员全权负责

1. 发送流程 (如何发出一个报文?)
在这里插入图片描述

  1. 程序操作
    • 选择一个空置的发送邮箱 (邮箱 0、1 或 2)。
    • 将报文的所有参数 (IDDataIDE (扩展标志)、RTR (远程帧标志)、DLC (数据长度码)) 写入该邮箱对应的寄存器。
    • 设置该邮箱的 TXRQ (Transmit Request) 寄存器位为 1,发出请求发送命令。
  2. 管理员的工作
    • 收到发送请求后,自动接管后续所有操作
    • 等待总线进入 空闲 (Idle) 状态。
    • 当总线空闲时,自动将该报文广播到 CAN 总线上,完成整个发送流程(包含位同步、仲裁、波形输出、位填充、错误检测、ACK 处理等)。
    • 报文成功发送后,释放该邮箱,使其恢复空置状态
  3. 为什么需要 3 个发送邮箱?
    • 核心目的防止因总线繁忙造成 CPU 等待 (发送拥堵)
    • 场景分析
      • 程序写入报文 A 到邮箱 0 并请求发送。
      • 管理员发现总线正忙,报文 A 在邮箱 0 中等待
      • 此时程序又想发送报文 B。如果只有一个邮箱,程序必须等待邮箱 0 空闲(即报文 A 发送完成)才能写入报文 B,造成 CPU 等待
      • 有了三个邮箱,程序发现邮箱 0 被占用,可以立即将报文 B 写入邮箱 1 并请求发送。管理员会在总线空闲时依次发送邮箱 0 和邮箱 1 的报文。CPU 无需等待,可以继续执行其他任务。
      • 同理,程序还可以将报文 C 写入邮箱 2
      • 极限情况:如果三个邮箱都写满总线持续繁忙,此时程序再想发送新报文 (D) 时,才需要等待某个邮箱释放。这种情况表示总线非常拥堵,在实际应用中相对少见。
    • 优势:三个邮箱提供了发送缓冲区,允许程序连续提交多个发送请求,显著减少了 CPU 因等待总线空闲而产生的阻塞时间
  4. 发送策略配置 (TXFP 位)
    • 多个邮箱中都有待发报文总线变为空闲时,管理员需要决定先发送哪个邮箱的报文
    • 策略可配置:
      • TXFP = 1先请求先发送 (FIFO 模式)。严格按照请求发送 (TXRQ=1) 的时间顺序处理邮箱(邮箱号顺序是次要的)。先请求的报文先发送
      • TXFP = 0按 ID 优先级发送。管理员会比较所有待发邮箱中报文的 ID 号优先发送 ID 值最小的报文(优先级最高)。ID 值相等时,优先发送邮箱号小的报文(如邮箱 0 优于邮箱 1)。此模式允许高优先级报文“插队”。

2. 接收流程 (如何接收想要的报文?)
在这里插入图片描述

  1. 管理员的工作 (第一步:捕获与过滤)
    • CAN 总线上出现任何数据帧或远程帧时,管理员都会自动捕获并完整接收该报文。
    • 接收到的报文首先经过 14 个标识符过滤器组
      • 过滤器作用:程序预先在过滤器组中配置规则(例如:只接收特定 ID 或 ID 范围的报文,屏蔽某些 ID 的报文)。硬件自动进行 ID 比对
      • 过滤结果
        • 报文 ID 匹配任何一个启用的过滤器规则 -> 报文是**“需要的”** -> 允许进入下一步
        • 报文 ID 无法匹配任何启用的过滤器规则 -> 报文是**“不需要的”** -> 管理员直接丢弃该报文,不会通知程序
    • 过滤器意义硬件级过滤极大地减轻了软件负担,软件无需处理海量的无关报文 ID 比对
  2. 管理员的工作 (第二步:排队存储)
    • 通过过滤器的报文(即“需要的”报文)不会直接交给程序
    • 它们会根据配置过滤器时指定的目标 FIFO (由程序设定),自动存入接收 FIFO0 或 FIFO1 的队列中排队等待
      • FIFO (先进先出队列):每个 FIFO (FIFO0, FIFO1) 都是一个队列,深度为 3 个邮箱。意味着每个 FIFO 最多可暂存 3 个报文
      • 报文存储规则
        • 新报文总是排在队列的末尾
        • 示例:配置 Filter0 通过的报文进 FIFO0Filter1 通过的报文进 FIFO1
          • 报文 A (通过 Filter0) -> 存入 FIFO0 邮箱 0 (队首)。
          • 报文 B (通过 Filter0) -> 存入 FIFO0 邮箱 1。
          • 报文 C (通过 Filter1) -> 存入 FIFO1 邮箱 0 (队首)。
          • 报文 D (通过 Filter0) -> 存入 FIFO0 邮箱 2。
          • 此时 FIFO0 已满 (3个报文)
  3. 程序操作 (读取)
    • 程序通过轮询或中断方式,检查 FIFO0FIFO1 的队列状态 (FMPx 寄存器位指示队列中报文数量)。
    • 当检测到某个 FIFO 队列长度大于 0 (有报文排队) 时:
      • 程序读取该 FIFO 队列头部 (最先存入,邮箱 0) 的报文数据。
      • 读取后,程序必须显式释放该邮箱 (RFOMx=1)。
      • 队列管理:释放队首邮箱后:
        • 邮箱 1 的报文前移到邮箱 0 (成为新队首)。
        • 邮箱 2 的报文前移到邮箱 1。
        • 队尾邮箱 (邮箱 2) 变为空置,可接收新报文。
      • 这个过程模拟了现实中排队新来者排到队尾,处理者从队首开始,处理完队首后后面的人依次前移。这就是 FIFO (先进先出) 名称的由来。
  4. FIFO 满溢处理 (RFLM 位)
    • 当某个 FIFO 队列已满 (3 个邮箱均占用) 时,如果又收到一个需存入该 FIFO 的报文:
      • RFLM = 1 (锁定模式)新报文直接丢弃
      • RFLM = 0 (非锁定模式 - 默认)新报文覆盖该 FIFO 队列中最后接收的报文 (即邮箱 2 中的报文)。原邮箱 2 的报文丢失
    • 队列满溢必然导致报文丢失:要么丢弃新报文 (RFLM=1),要么覆盖最旧的排队报文 (RFLM=0)。
  5. 为什么需要 2 个接收 FIFO? (分流策略)
    • 核心目的降低重要报文在接收拥堵时的丢失概率
    • 类比:食堂设学生窗口教师窗口。即使学生窗口排长队拥堵,教师仍能在教师窗口快速打饭,保证教师(重要角色)能准时吃饭
    • 应用
      • 重要、紧急或数量较少的报文 (如关键控制指令、报警信号) 配置到 FIFO0
      • 普通、非关键或数量较大的报文 (如常规状态更新) 配置到 FIFO1
    • 优势
      • 即使 FIFO1 因大量普通报文涌入而频繁满溢重要报文仍然可以在 FIFO0 中被可靠接收(除非 FIFO0 自己也满了)。
      • 相比于所有报文挤在单一 FIFO 队列中(容易导致重要报文排在后面被覆盖或丢弃),双 FIFO 分流显著提高了重要报文的接收可靠性
    • 注意:STM32 硬件本身并未赋予 FIFO0FIFO1 不同的优先级,它们是平级的。程序可以根据自身需求(报文重要性、类型、接收频率)灵活配置分流规则

发送邮箱 vs. 接收 FIFO (本质都是缓冲队列)

  • 共同点:两者都在数据写入速率 (CPU 提交发送请求 / 管理员 存入接收报文) 大于数据处理速率 (管理员 实际发送 / CPU 读取接收报文) 时,提供缓冲能力,避免数据丢失或 CPU 阻塞
  • 差异点
    • 接收 FIFO:只支持严格的先进先出 (FIFO) 排队策略。
    • 发送邮箱:排队策略可配置 (TXFP 位),支持 FIFO (TXFP=1) 或 ID 优先级 (TXFP=0)。
  • 理想情况:如果数据处理速率远高于写入速率(发送:总线总是很快空闲;接收:CPU 总是及时读取),队列基本不会堆积,缓冲作用不明显。但在实际应用中,缓冲队列对于应对突发流量和短暂拥堵至关重要

通过以上详细流程解析,STM32 CAN 外设 (bxCAN) 处理报文发送与接收的核心机制就非常清晰了。


2.1.4 发送流程详解

在这里插入图片描述

好的,这是按照您要求的格式(保留加粗,无省略知识点,无引用符号)校正优化后的文本,详细描述了 STM32 CAN 发送邮箱的状态流转及其寄存器标志位

STM32 CAN 发送邮箱状态流转详解

接下来,我们深入探讨 发送邮箱在报文发送过程中经历的各种状态及其状态寄存器标志位的变化。理解这个状态机对于掌握发送流程和控制至关重要。

核心状态寄存器标志位 (需关注):

  • TME (Transmit mailbox empty)发送邮箱空1 表示邮箱空闲可用0 表示邮箱已被占用(有报文待发或正在发送)。
  • TXRQ (Transmit request)发送请求。由程序置 1请求发送该邮箱中的报文。硬件在发送完成或失败后清除此位。
  • RQCP (Request completed)请求完成1 表示对该邮箱的发送请求已完成(无论成功或失败);0 表示请求未完成/正在进行中
  • TXOK (Transmission OK)发送成功1 表示报文成功发送(收到有效 ACK 且无错误);0 表示发送未成功尚未完成
  • ABRQ (Abort request)中止请求。由程序置 1请求中止该邮箱的发送。
  • NART (No automatic retransmission)禁止自动重传(全局配置位)。0 启用自动重传;1 禁止自动重传。

发送邮箱状态机 (单个邮箱视角):

  1. 空置状态 (Empty)

    • 标志位TME = 1, RQCP = X (任意), TXOK = X (任意)。
    • 含义:邮箱空闲,程序可向其写入新报文
    • 进入条件:初始状态,或发送完成/失败/中止后。
    • 操作:程序写入报文参数 (ID, Data, IDE, RTR, DLC) 并设置 TXRQ = 1
  2. 挂号状态 (Pending)

    • 标志位TME = 0, TXRQ = 1, RQCP = 0, TXOK = 0
    • 含义:报文已写入邮箱,发送请求 (TXRQ=1) 已发出,等待参与发送调度
    • 进入条件:在空置状态写入报文并设置 TXRQ=1
    • 状态行为
      • 该邮箱的报文已准备好发送
      • 由于存在多个邮箱 (0, 1, 2),且可能都有待发报文,因此需要确定发送顺序
    • 后续状态:当该邮箱的报文根据 TXFP 配置的发送策略被确定为当前最高优先级时,进入预定状态
  3. 预定状态 (Scheduled)

    • 标志位TME = 0, TXRQ = 1, RQCP = 0, TXOK = 0。(标志位与挂号状态相同,由内部逻辑区分)。
    • 含义:该邮箱的报文已被管理员调度为“下一个发送”一旦总线空闲 (IDLE),即开始发送。
    • 进入条件:从挂号状态提升而来,前提是该邮箱报文的优先级是当前所有挂号邮箱中最高的
      • 优先级决定方式 (TXFP)
        • TXFP = 1 (FIFO 模式 - 先请求先发送):优先级仅由请求发送 (TXRQ=1) 的时间顺序决定一旦进入预定状态,不会退回挂号状态(先来者不会“被插队”)。
        • TXFP = 0 (ID 优先级模式):优先级由报文 ID 值决定(ID 值小者优先级高;ID 相等时邮箱号小者优先)。在这种模式下,如果一个具有更高优先级 (更小 ID) 的报文被写入另一个邮箱并请求发送 (TXRQ=1),当前处于预定状态的邮箱可能被“抢占”退回挂号状态等待。
    • 后续状态:当检测到总线空闲 (IDLE) 时,进入发送状态
  4. 发送状态 (Transmit)

    • 标志位TME = 0, TXRQ = 1, RQCP = 0, TXOK = 0。(标志位仍与挂号/预定状态相同,由内部逻辑区分)。
    • 含义:该邮箱的报文正在被管理员实际发送到 CAN 总线上(进行位同步、驱动 TX 引脚、仲裁、填充、错误检测、等待 ACK 等操作)。
    • 进入条件:从预定状态进入,当总线空闲时。
    • 后续状态 (发送结束)
      • 发送成功 (收到有效 ACK 且未检测到错误):
        • 状态回到空置状态
        • 设置标志位:TME = 1, RQCP = 1, TXOK = 1
      • 发送失败 (仲裁丢失、未收到 ACK、检测到位错误等):
        • 取决于 NART
          • NART = 0 (启用自动重传):状态回到预定状态 (TME=0, TXRQ=1, RQCP=0, TXOK=0)。硬件将自动尝试重发该报文,直到成功。
          • NART = 1 (禁止自动重传):状态直接回到空置状态
            • 设置标志位:TME = 1, RQCP = 1, TXOK = 0 (表示请求已完成但发送失败)。
      • 程序中止 (ABRQ = 1)
        • 状态回到空置状态
        • 设置标志位:TME = 1, RQCP = 1, TXOK = 0 (表示请求被中止,发送未成功)。

关键状态转换补充:

  • 中止发送 (ABRQ):程序可以在邮箱处于挂号状态 (TME=0, TXRQ=1, RQCP=0, TXOK=0)预定状态 (TME=0, TXRQ=1, RQCP=0, TXOK=0) 时(即报文尚未实际开始驱动总线波形),通过设置 ABRQ = 1主动终止该次发送请求。效果与 NART=1 时的发送失败相同:直接进入空置状态,RQCP=1, TXOK=0
  • 预定状态回退仅发生在 TXFP=0 (ID 优先级模式)有更高优先级报文加入并请求发送时。该邮箱会从预定状态退回到挂号状态 (TME=0, TXRQ=1, RQCP=0, TXOK=0),等待再次被调度。

2.1.5 接收流程详解

接下来,我们聚焦于 接收 FIFO (FIFO0 或 FIFO1) 在报文接收、存储和读取过程中经历的状态及其状态寄存器标志位的变化。理解这个状态机对于掌握接收流程和管理 FIFO 队列至关重要。在这里插入图片描述
STM32 CAN 接收 FIFO 状态流转详解

核心状态寄存器标志位 (需关注):

  • FMPx (FIFO message pending - x=0 or 1)FIFO 中挂起的报文数量。这是一个 2 位字段:
    • 00b0 个报文 (FIFO 空)。
    • 01b1 个报文
    • 10b2 个报文
    • 11b3 个报文 (FIFO 满)。
  • FOVRx (FIFO overrun - x=0 or 1)FIFO 溢出标志1 表示自上次该标志被清除以来,该 FIFO 曾发生过溢出(即 FIFO 满时又收到新报文);0 表示未发生溢出。
  • FULLx (FIFO full - x=0 or 1)FIFO 满标志1 表示该 FIFO 的 3 个邮箱已全部占用0 表示 FIFO 未满(有至少一个空邮箱)。(注:此标志位在手册提供的流程图中未明确标出,但实际存在且重要)
  • RFOMx (Release FIFO output mailbox - x=0 or 1)释放 FIFO 输出邮箱。程序通过1 此位释放当前位于 FIFO 队列头部的邮箱(即 FIFOx 邮箱 0),使队列后续报文前移。

接收 FIFO 状态机 (单个 FIFO 视角):

  1. 空状态 (Empty)

    • 标志位FMPx = 00b (0), FOVRx = 0, FULLx = 0
    • 含义FIFO 队列为空,无任何报文等待处理。所有 3 个邮箱均空闲。
    • 进入条件:初始状态,或所有报文被读取释放后。
    • 操作:等待有效报文存入。
  2. 挂号一状态 (Pending 1)

    • 标志位FMPx = 01b (1), FOVRx = 0, FULLx = 0
    • 含义FIFO 队列中有 1 个报文(位于邮箱 0),等待程序读取。FIFO 未满未溢出
    • 进入条件:从空状态接收到第 1 个有效报文(通过过滤器且目标为此 FIFO)。
    • 操作:程序可读取 FIFOx 邮箱 0 的数据。
  3. 挂号二状态 (Pending 2)

    • 标志位FMPx = 10b (2), FOVRx = 0, FULLx = 0
    • 含义FIFO 队列中有 2 个报文(邮箱 0 和 邮箱 1),按接收顺序排队。FIFO 未满未溢出
    • 进入条件:从挂号一状态接收到第 2 个有效报文
    • 操作:程序可读取 FIFOx 邮箱 0 (队首) 的数据。
    • 手册勘误说明:手册流程图此处将 FMPx 写作 0x10 (十六进制 16),这是错误的。正确应为 10b (二进制 2) 或明确表示为 2
  4. 挂号三状态 (Pending 3 / Full)

    • 标志位FMPx = 11b (3), FOVRx = 0, FULLx = 1
    • 含义FIFO 队列已满3 个邮箱均已占用(邮箱 0, 1, 2)。FIFO 已满 (FULLx=1),但尚未溢出 (FOVRx=0)。这是 FIFO 的最大容量状态
    • 进入条件:从挂号二状态接收到第 3 个有效报文
    • 操作:程序可读取 FIFOx 邮箱 0 (队首) 的数据。
  5. 溢出状态 (Overrun)

    • 标志位FMPx = 11b (3), FOVRx = 1, FULLx = 1
    • 含义FIFO 队列已满 (FMPx=11b, FULLx=1) 的状态下,又收到了一个需存入该 FIFO 的有效报文。此时发生了溢出 (FOVRx=1)。
    • 进入条件:在挂号三状态 (已满) 时,接收到第 4 个 (及更多) 有效报文
    • 溢出处理 (取决于 RFLM 配置位)
      • RFLM = 1 (锁定模式)新报文被直接丢弃。FIFO 内容 (FMPx=11b) 保持不变。
      • RFLM = 0 (非锁定模式 - 默认)新报文覆盖队列中最后接收的报文(即邮箱 2 中的旧报文)。FMPxFULLx 保持 11b1,表示队列仍满,但内容已更新(邮箱 2 被替换)。
    • 状态维持:只要 FIFO 保持满状态 (FMPx=11b) 且不断有新的目标报文到来,FOVRx 将保持为 1,状态维持为溢出状态。每次新报文到来都会根据 RFLM 执行丢弃或覆盖操作。

FIFO 读取与释放操作:

  • 操作前提:当 FMPx > 00b (FIFO 非空) 时,程序可以读取 FIFOx 邮箱 0 的报文数据。
  • 关键操作 - 释放邮箱 (RFOMx=1):读取完邮箱 0 的数据后,程序必须置 RFOMx=1释放该邮箱
  • 释放后的队列管理
    • 释放操作触发队列前移
      • 邮箱 1 的报文 -> 移动到邮箱 0 (成为新队首)。
      • 邮箱 2 的报文 -> 移动到邮箱 1
      • 原邮箱 2 的位置变为空闲 (可接收新报文)。
    • FMPx减 1
    • 如果 FOVRx=1,它不会被自动清除,需要软件在适当时机手动清除。
  • 状态转换 (释放后)
    • 溢出状态 (FMPx=11b, FOVRx=1, FULLx=1) 释放邮箱:
      • FMPx 变为 10b (2)。
      • FULLx 变为 0 (队列未满)。
      • 状态直接进入挂号二状态 (FMPx=10b, FOVRx=1, FULLx=0)
      • 重要说明不需要经过挂号三状态。溢出状态和挂号三状态的主要区别在于 FOVRx 标志位。释放邮箱后,FMPx 从 3 减为 2,队列未满,故直接进入挂号二状态。FOVRx=1 仍然有效,指示曾发生过溢出。
    • 挂号三状态 (FMPx=11b, FOVRx=0, FULLx=1) 释放邮箱:
      • FMPx 变为 10b (2).
      • FULLx 变为 0.
      • 状态进入挂号二状态 (FMPx=10b, FOVRx=0, FULLx=0)
    • 挂号二状态 (FMPx=10b, FOVRx=0, FULLx=0) 释放邮箱:
      • FMPx 变为 01b (1).
      • 状态进入挂号一状态 (FMPx=01b, FOVRx=0, FULLx=0)
    • 挂号一状态 (FMPx=01b, FOVRx=0, FULLx=0) 释放邮箱:
      • FMPx 变为 00b (0).
      • 状态回到空状态 (FMPx=00b, FOVRx=0, FULLx=0)

2.1.6 关键配置位总结

在这里插入图片描述

  1. NART (No automatic retransmission)
    • 1禁止自动重传。报文只发送一次(无论成功失败)。
    • 0启用自动重传 (默认)。发送失败会重试直至成功。
  2. TXFP (Transmit FIFO priority)
    • 1:发送优先级由请求顺序决定 (先请求先发送)。
    • 0:发送优先级由报文标识符(ID) 决定 (ID小者优先)。
  3. RFLM (Receive FIFO locked mode)
    • 1:接收FIFO 锁定模式。FIFO满时新报文丢弃
    • 0:接收FIFO 非锁定模式 (默认)。FIFO满时新报文覆盖FIFO末尾旧报文

本节总结
我们详细讲解了 STM32 bxCAN外设的核心结构、发送邮箱的状态流转、接收过滤器双FIFO的工作机制以及关键配置位(NART, TXFP, RFLM)。掌握了这些硬件原理,为下一部分编写实际通信程序奠定了坚实基础。

下一节预告:我们将深入探讨 CAN外设的标识符过滤器配置 及更多功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/93392.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/93392.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能技术革命:AI工具与大模型如何重塑开发者工作模式与行业格局

引言:AI技术爆发的时代背景过去五年间,人工智能领域经历了前所未有的爆发式增长。从2020年GPT-3的横空出世到2023年多模态大模型的全面突破,AI技术已经从实验室走向了产业应用的前沿。开发者作为技术生态的核心推动者,其工作模式正…

傅里叶变换

傅里叶变换:运用频域的出发点就是能够将波形从时域变换到频域,用傅里叶变换可以做到这一点。有如下3种傅里叶变换类型:1.傅里叶积分(FI); 2.离散傅里叶变换(DFT); 3.快速傅里叶变换(FFT)。傅里叶积分是一种将时域的理想数学表达变换成频域描述的数学技术…

【IQA技术专题】纹理相似度图像评价指标DISTS

纹理一致性图像评价指标: Image Quality Assessment: Unifying Structure and Texture Similarity(2020 PAMI)专题介绍一、研究背景二、方法总览2.1 初始变换2.2 纹理表示和结构表示2.3 DISTS指标2.4 优化DISTS指标三、实验结果四、总结本文将对统一图像…

windows下Docker安装路径、存储路径修改

一、命令行指定安装路径​ ​​下载安装包​​:从Docker官网获取安装程序(如Docker Desktop Installer.exe)。​​运行PowerShell​​: & "H:\Docker Desktop Installer.exe" install --installation-dir"F:…

thingsboard 自定义动作JS编程

在 ThingsBoard 中实现 自定义动作(Custom Action)的 JavaScript 编程,主要通过“Custom action (with HTML template)”方式完成,适用于创建弹窗、编辑实体、控制设备等交互行为。 实现步骤(以添加设备或资…

Spring Boot 简单接口角色授权检查实现

一、背景与目标在Spring Boot应用开发中,接口级别的权限控制是系统安全的重要组成部分。本文将介绍一种简单直接的接口角色授权检查实现方案,适合快速开发和安全合规检查场景。二、技术方案概述本方案采用自定义注解拦截器的方式实现,具有以下…

PytorchLightning最佳实践日志篇

在 PyTorch Lightning(PL)中,日志系统是 “炼丹” 过程中复现实验、对比效果、排查问题的核心工具。结合实际工程经验,总结以下最佳实践和技巧,帮助提升实验效率: 一、日志工具的选择与配置 PL 通过统一的s…

基于JavaWeb的兼职发布平台的设计与实现

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7数据库工具:Navicat12开发软件:eclipse/myeclipse/ideaMaven包:Maven3.6系统展示系统首页用户登录招聘信…

Linux学习--C语言(指针3)

1.指针函数和函数指针1.1 指针函数指针函数是函数&#xff0c;函数的返回值是指针不能返回局部变量的地址指针函数返回的地址可以作为下一个函数调用的参数1.2 函数指针函数指针是指针&#xff0c;指针指向一个函数#include <stdio.h>int Add(int x, int y) {return x y…

【JAVA EE初阶】多线程(上)

目录 1.预备知识 1.1 冯诺依曼体系结构&#xff1a; 1.2 现代CPU主要关心指标&#xff08;和日常开发密切相关的&#xff09; 1.3 计算机中&#xff0c;一个汉字占几个字节&#xff1f; 1.4 Windows和Linux的区别 1.5 PCB的一些关键要点 2.线程和进程 2.1 创建线程的写法…

用互联网思维扩展电商后台的 CRUD 功能

一、自定义实现MyBatis-Plus逆向工程 多数据源的问题解决了&#xff0c;接下来开始进行实际开发时&#xff0c;你会发现&#xff0c;最麻烦的一件事情就是要创建与数据库表对应的POJO了。这些没什么难度&#xff0c;但是繁琐的内容会占据大量的开发时间。比如一个PmsProducr对…

无代码测试平台ATECLOUD全场景测试方案

ATECLOUD 智能云测试平台是有纳米软件开发的一款以无代码架构与弹性扩展体系为核心的自动化测试平台&#xff0c;通过数据模型驱动的创新设计&#xff0c;为研发、产线等多场景提供高效可控的测试解决方案。​无代码架构 ATECLOUD 打破传统技术壁垒&#xff0c;构建完全可视化的…

当 AI 重构审计流程,CISA 认证为何成为破局关键

在南京审计大学最新发布的《面向审计行业 DeepSeek 大模型操作指南》中&#xff0c;一组数据引发行业深思&#xff1a;通过自动化数据处理、智能风险识别和定制化报告生成&#xff0c;AI 大模型能帮助审计人员降低 40% 以上的人工成本&#xff0c;同时将风险识别准确率提升至 9…

NAT技术、代理服务器

NAT/NAPT技术NAT的全称是network address translation&#xff0c;网络地址转换。NAT 能在对外通信时够将源 IP 转为新源 IP&#xff0c;对内通信时将目的ip转换成新目的ip&#xff0c;实现这个操作&#xff0c;靠的是地址转换表但NAT的说法其实是不准确的&#xff0c;因为多个…

【硬件-笔试面试题】硬件/电子工程师,笔试面试题-45,(知识点:负反馈的作用,基础理解,干扰和噪声的抑制)

目录 1、题目 2、解答 步骤一&#xff1a;明确负反馈的作用原理 步骤二&#xff1a;逐一分析选项 3、相关知识点 一、负反馈的基本原理 二、负反馈对干扰和噪声的抑制机制 三、选项分析与答案 四、扩展思考&#xff1a;如何抑制不同位置的干扰&#xff1f; 总结 题目…

Flutter蓝牙BLE开发完全指南(内含高级功能扩展)

Flutter蓝牙BLE开发完全指南 我将为您提供一个完整的Flutter蓝牙BLE实现方案,包含UI设计、权限处理、设备扫描、连接通信等完整功能。 完整实现方案 1. 添加依赖与权限配置 pubspec.yaml dependencies:flutter:sdk: flutterflutter_blue_plus: ^1.10.0permission_handler…

使用 Canvas 替代 <video> 标签加载并渲染视频

在部分浏览器环境或业务场景下&#xff0c;直接使用 <video> 标签加载视频会出现首帧延迟的情况。以下方法通过 WebGPU Canvas 2D 将视频帧绘制到自定义 Canvas 上&#xff0c;让 <video> 只做解码&#xff0c;WebGPU 接管渲染&#xff0c;通过最小化对象创建 精…

基于Flask的智能停车场管理系统开发实践

在现代城市中&#xff0c;停车难已成为一个普遍问题。为了解决这一问题&#xff0c;我开发了一个基于Python Flask框架的智能停车场管理系统。该系统集成了车牌识别、车位状态监控、收费管理等多项功能&#xff0c;为停车场的智能化管理提供了完整的解决方案。系统功能概述该停…

【C#获取高精度时间】

在C#中&#xff0c;有几种方法可以获取高精度时间&#xff08;高分辨率时间戳&#xff09;&#xff0c;适用于性能测量、计时等需要高精度的场景。以下是几种常用方法&#xff1a; 1. 使用 Stopwatch 类&#xff08;推荐&#xff09; Stopwatch 类提供了最高精度的时间测量&…

Spring Boot + React 打造现代化高校成绩管理系统实战记录

作者: 笙囧同学 发布时间: 2025年7月 技术栈: Spring Boot 3.2.3 React 18 TypeScript 华为云GaussDB 项目类型: 全栈Web应用 开发周期: 30天 代码量: 15000 行 &#x1f4d6; 前言 大家好&#xff0c;我是笙囧同学&#xff01;&#x1f64b;‍♂️ 作为一名计算机科学与技…