什么是寄存器?(STM32)

2023-05-16

什么是寄存器?

我们现在在开发STM32时,已经很少用到寄存器编程,更多的使用ST公司所提供的标准库和最新的HAL库进行编程实现,但是不管是标准库还是HAL库都是在原来的寄存器层面上进行了封装,知道寄存器是什么,还是很重要的,了解寄存器的原来,对我们使用标准库和HAL库也是有很大的帮助。我下面会以STM32F103VET6为例,解释寄存器到底是什么?

在STM32编程,实际上就是通过程序控制这些引脚输出高低电平来控制各种传感器工作

下图是STM32F103VET6的引脚分布图

image-20230110215753331

我们常见的STM32芯片是已经封装好的成品,主要是由内核和片上外设组成,就像电脑中的CPU和主板、内存、显卡、硬盘的关系。

STM32F103采用的是Cortex-M3内核,内核就是CPU,它由ARM公司设计,ST公司生产,ST负责设计内核之外的整个芯片,这些内核之外的部件,被称为片上外设。例如GPIO、USART、I2C、SPI等都叫做片上外设

image-20230110220712782

上图是STM32芯片架构简图

内核和各种外设之间是通过各种总线连接,听到总线,应该不少人听过电脑中的南桥北桥总线,其实我们STM32中也是一样的,STM32中的驱动单元是4个,被动单元也是4个,我们把驱动单元当成CPU的一部分,同样可以将被动单元当成外设,下面我将介绍驱动单元和被动单元的各个部件。

ICode总线

I代表Instruction,即命令,我们程序编译后都是一条条指令,存于FLASH中,内核通过ICode总线来读取这些指令,进而根据这些指令执行程序,它是专门用来读取指令的。

驱动单元

DCode总线

D是数据Data,即数据,说明这条总线是用来读取数据的,我们知道数据分为常量和变量,常量是固定不变的,在C语言中常量是用const关键字修饰的,它存放在FLASH中,变量是可变的,不管是局部变量还是全局变量,都存放在SRAM中,数据可以被DCode总线和DMA总线访问,为了避免冲突,在读取的时候需要一个总线矩阵来进行总裁,决定哪个总线在读取数据。

系统总线

系统总线主要是用于访问外设的寄存器,我们经常说的寄存器编程,即读写寄存器,都是通过这根系统总线来完成的。

DMA总线

DMA总线主要用于传输数据,数据可以是某个外设的数据寄存器,也可以是SRAM,也可以是内部的FLASH,因为数据可以被 Dcode 总线和 DMA 总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数。

被动单元

内部的闪存存储器

即FALSH,用于存放编写好的程序,内核通过ICode总线来取里面的指令

内部的SRAM

就是我们常说的RAM,程序的变量,以及堆栈的开销都是基于SRAM的。内核通过DCode总线来访问它

FSMC

全称,灵活的静态的存储器控制器,也是STM32的一个外设,通过该外设我们可以扩展内存,如外部的SRAM等,但是FSMC只能扩展静态的内存,像动态内存SDRAM就不能扩展

AHB到APB的桥

从AHB总线延伸出来的两条APB2和APB1总线,上面挂在这STM32的各种各样的外设,就是我们经常说的GPIO、串口、I2C、SPI这些外设就挂载在这两条总线上,我们学习STM32,就是学会利用编程这些外设去驱动外部的各种设备。

image-20230110223555144

​ STM32F10XX系统框图

在上图中,被控单元的FLASH,RAM,FSMC和AHB到APB2的桥,这些功能部件共同排列在一个4GB的地址空间中,在编程时,我们可以通过它们的地址找到它们,然后操作。

存储器映射

存储器本身不具有地址信息,它的地址是由芯片厂商或者用户分配的,给存储器分配地址的过程就称为存储器映射。如果给存储器再分配一个地址就叫做存储器重映射。

截屏2023-01-10 22.41.11

在这4GB的地址空间中,ARM被粗细线条分成了8个块,每块512M,每块都规定了用途,芯片厂商在每个块的范围内设计外设时并不一定用得完,都只是用了其中的一部分。

image-20230110224455915

寄存器映射

铺垫了那么多,是为了更好的理解寄存器是什么,简而言之寄存器就是内存,我们都知道,寄存器本身没有地址,给寄存器分配地址的过程叫寄存器映射,那么什么是寄存器映射呢?

在存储器中的某片区域,设计的是片上外设,它们以4个字节为一个单元,共32bit,每一个单元对应不同的功能,我们通过控制这些单元就可以驱动外设工作。我们可以先找到每个单元的起始地址,然后通过C语言的指针的操作方式来访问这些单元,但是每次都要通过地址的方式访问,难记忆也容易出错,于是,我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们常说的寄存器,给已经分配好地址的有特定功能的内存单元取别名的过程就叫做寄存器映射。

比如,我们找到 GPIOB 端口的输出数据寄存器 ODR 的地址是 0x4001 0C0CODR ,寄存器是 32bit,低 16bit有效,对应着 16 个外部 IO,写 0/1 对应的的 IO 则输出低/高电平。现在我们通过 C 语言指针的操作方式,让 GPIOB 的 16 个 IO 都输出高电平

// GPIOB 端口全部输出 高电平
*(unsigned int*)(0x4001 0C0C) = 0xFFFF;

0x4001 0C0C 在我们看来是 GPIOB 端口 ODR 的地址,但是在编译器看来,这只是一个普通的变量,是一个立即数,要想让编译器也认为是指针,我们得进行强制类型转换,把它转换成指针,即(unsigned int *)0x4001 0C0C,然后再对这个指针进行 * 操作。

刚才我们说了,通过绝对地址访问内存单元不好记忆且容易出错,我们可以通过寄存器的方式来操作

// GPIOB 端口全部输出 高电平
#define GPIOB_ODR           //(unsigned int*)(GPIOB_BASE+0x0C)
*GPIOB_ODR = 0xFF;

为了操作方便,我们也直接把指针操作的“*”也定义到寄存器中

// GPIOB 端口全部输出 高电平
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE+0x0C)
GPIOB_ODR = 0xFF;
STM的外设地址映射

片上外设分为三条线,根据外设速度的不同,不同总线挂载着不同的外设,APB1挂载低速外设,APB2和AHB挂在高速外设。对应总线的最低地址称为总线的基地址,总线基地址也是挂载在这个总线上的首个外设的地址,其中APB1总线地址最低,片上外设从这里开始,也叫做外设基地址

image-20230110230011356

外设寄存器

在 XX 外设的地址范围内,分布着的就是该外设的寄存器。以 GPIO 外设为例, GPIO是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,基本功能是控制引脚输出高电平或者低电平。最简单的应用就是把 GPIO 的引脚连接到 LED 灯的阴极, LED 灯的阳极接电源,然后通过 STM32 控制该引脚的电平,从而实现控制 LED 灯的亮灭。GPIO 有很多个寄存器,每一个都有特定的功能。每个寄存器为 32bit,占四个字节,在该外设的基地址上按照顺序排列,寄存器的位置都以相对该外设基地址的偏移地址来描
述。这里我们以 GPIOB 端口为例,来说明 GPIO 都有哪些寄存器

image-20230110230146872

这里以端口置位/复位寄存器为例

image-20230110230247423

(GPIOx_BSSR)(x=A…E)这段的意思是该寄存器为GPIOx_BSSR其中的“x”可以是A-E,也就是这个寄存器适用于GPIOA、GPIOB至GPIOE,所有GPIO端口都有这样的一个寄存器

偏移地址是指本寄存器相对于这个外设的基地址的偏移。本寄存器的偏移地址是 0x18,从参考手册中我们可以查到 GPIOA 外设的基地址为 0x4001 0800 ,我们就可以算出GPIOA 的这个 GPIOA_BSRR 寄存器的地址为: 0x4001 0800+0x18 ;同理,由于 GPIOB 的外设基地址为 0x4001 0C00,可算出 GPIOB_BSRR 寄存器的地址为: 0x4001 0C00+0x18 。其他 GPIO 端口以此类推即可。

紧接着的是本寄存器的位表,表中列出它的 0-31 位的名称及权限。表上方的数字为位编号,中间为位名称,最下方为读写权限,其中 w 表示只写, r 表示只读, rw 表示可读写。本寄存器中的位权限都是 w,所以只能写,如果读本寄存器,是无法保证读取到它真正内容的。而有的寄存器位只读,一般是用于表示 STM32 外设的某种工作状态的,由 STM32硬件自动更改,程序通过读取那些寄存器位来判断外设的工作状态位功能是寄存器说明中最重要的部分,它详细介绍了寄存器每一个位的功能。例如本寄存器中有两种寄存器位,分别为 BRy 及 BSy,其中的 y 数值可以是 0-15,这里的 0-15表示端口的引脚号,如 BR0、 BS0 用于控制 GPIOx 的第 0 个引脚,若 x 表示 GPIOA,那就是控制 GPIOA 的第 0 引脚,而 BR1、 BS1 就是控制 GPIOA 第 1 个引脚。
其中 BRy 引脚的说明是“0:不会对相应的 ODRx 位执行任何操作; 1:对相应 ODRx位进行复位”。这里的“复位”是将该位设置为 0 的意思,而“置位”表示将该位设置为
1;说明中的 ODRx 是另一个寄存器的寄存器位,我们只需要知道 ODRx 位为 1 的时候,对应的引脚 x 输出高电平,为 0 的时候对应的引脚输出低电平即可(感兴趣的读者可以查询该寄存器 GPIOx_ODR 的说明了解)。所以,如果对 BR0 写入“ 1”的话,那么 GPIOx 的第0 个引脚就会输出“低电平”,但是对 BR0 写入“ 0”的话,却不会影响 ODR0 位,所以引脚电平不会改变。要想该引脚输出“高电平”,就需要对“ BS0”位写入“ 1”,寄存器位BSy 与 BRy 是相反的操作

封装总线和外设基地址

在编程上为了方便记忆,我们把总线基地址和外设基地址都以相应的宏定义起来,总线或者外设都以它们的名字作为宏名

image-20230110231120648

首先定义了 “片上外设”基地址 PERIPH_BASE,接着在 PERIPH_BASE 上
加入各个 总线 的地址 偏移, 得到 APB1、 APB2 总线 的地址 APB1PERIPH_BASE
APB2PERIPH_BASE,在其之上加入外设地址的偏移,得到 GPIOA-G 的外设地址,最后在外设地址上加入各寄存器的地址偏移,得到特定寄存器的地址。一旦有了具体地址,就可以用指针读写。

image-20230110231242325

该代码使用 (unsigned int ) 把 GPIOB_BSRR 宏的数值强制转换成了地址,然后再用
”号做取指针操作,对该地址的赋值,从而实现了写寄存器的功能。同样,读寄存器也是用取指针操作,把寄存器中的数据取到变量里,从而获取 STM32 外设的状态

用上面的方法去定义地址,还是稍显繁琐,例如 GPIOA-GPIOE 都各有一组功能相同的寄存器,如 GPIOA_ODR/GPIOB_ODR/GPIOC_ODR 等等,它们只是地址不一样,但却要为每个寄存器都定义它的地址。为了更方便地访问寄存器,我们引入 C 语言中的结构体语法对寄存器进行封装,

image-20230110231341859

这段代码用 typedef 关键字声明了名为 GPIO_TypeDef 的结构体类型,结构体内有 7 个成员变量,变量名正好对应寄存器的名字。 C 语言的语法规定,结构体内变量的存储空间是连续的,其中 32 位的变量占用 4 个字节, 16 位的变量占用 2 个字节

image-20230110231446351

也就是说,我们定义的这个 GPIO_TypeDef , 假如这个结构体的首地址为 0x4001
0C00( 这也是第一个成员变量 CRL 的地址) , 那么结构体中第二个成员变量 CRH 的地址即为 0x4001 0C00 +0x04 , 加上的这个 0x04 ,正是代表 CRL 所占用的 4 个字节地址的偏移量,其它成员变量相对于结构体首地址的偏移

最后,我们更进一步,直接使用宏定义好 GPIO_TypeDef 类型的指针,而且指针指向各个 GPIO 端口的首地址,使用时我们直接用该宏访问寄存器即可

image-20230110231636332

这里只是以GPIO这个外设为例,讲解了C语言对寄存器的封装,以此类推,其他外设也可以用这种方法来封装,不过现在这部分工作都由固件库帮我们完
成了,这里我们只是分析了下这个封装的过程,让大家知其然,也只其所以然
本文主要参考了野火的资料

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么是寄存器?(STM32) 的相关文章

  • 处理器指令周期执行时间

    我的猜测是 no operation 内在 ARM 指令应花费 1 168 MHz 来执行 前提是每个NOP在一个时钟周期内执行 我想通过文档验证这一点 有关处理器指令周期执行时间的信息是否有标准位置 我试图确定 STM32f407IGh6
  • 初始化 ST-Link 设备时出错 - 无法连接到设备

    我目前正在使用 ST Link 调试器对我的 STM32F3 Discovery 板进行编程 我使用的IDE是Atollic TrueStudio 5 5 2 现在我面临一个非常奇怪的问题 那就是我不断收到消息 初始化 ST Link 设备
  • 在 MCU 内部 FLASH 中从一个固件跳转到另一个固件

    我目前正在开发针对 STM32F030C8 的引导加载程序固件应用程序 我在分散文件中指定引导加载程序应用程序将占用主内存位置 0x08000000 到 0x08002FFF 扇区 0 到扇区 2 我还编写了一个主固件应用程序 存储在0x0
  • 138-基于stm32单片机汽车多功能仪表盘显示系统Proteus仿真+源程序

    资料编号 138 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 ds1302时钟 LED灯 蜂鸣器 电位器 制作一个基于stm32单片机汽车多功能仪表盘显示系统Proteus仿真 2 通过DHT1
  • 136-基于stm32单片机家庭温湿度防漏水系统设计Proteus仿真+源程序

    资料编号 136 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 蜂鸣器 制作一个基于stm32单片机家庭温湿度防漏水系统设计Proteus仿真 2 通过DHT11传感器检测当前温湿度 并且显示到L
  • rt-thread studio中新建5.02版本报错

    先吐槽一下 rt thread studio出现BUG真多 好多时间都是在找BUG 但里面用好多控件还是挺好用的 真是又爱又恨 所以一般使用功能不多的话还是用keil多一点 创建5 02版本工程之后直接进行编译 直接会报下面这个错误 资源
  • Push_back() 导致程序在进入 main() 之前停止

    我正在为我的 STM32F3 Discovery 板使用 C 进行开发 并使用 std deque 作为队列 在尝试调试我的代码 直接在带有 ST link 的设备上或在模拟器中 后 代码最终在 main 中输入我的代码之前在断点处停止 然
  • STM32F103概要

    The STM32F103x4 STM32F103x6 STM32F103xC STM32F103xD and STM32F103xE are a drop in replacement for STM32F103x8 B medium d
  • 在 Atollic TrueStudio、STM32CubeMX 中导入 C 库

    我目前正在开发 STM32F767ZI Nucleo 板和一个小安全芯片 microchip atecc508a 通过 i2c 连接进行连接 该芯片有一个可用的库加密验证库 https github com MicrochipTech cr
  • 擦除后无法写入闪存

    所以我不能在擦除后直接写入内部闪存 如果写操作之前没有擦除操作 那么我可以 有什么想法吗 编程函数返回 成功写入 值 但查看内存时 没有写入任何数据 这是代码 uint32 t pageAddress 0x08008000 uint16 t
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false
  • STM32F207 I2C 测试失败

    我正在使用 STM32F207 微控制器在 STM3220G EVAL 板上学习嵌入式开发 我尝试通过连接同一芯片上的两个 I2C2 和 I2C3 模块并发送 接收字符来测试 I2C 接口 这是我当前编写的代码 使用 mdk arm 5 i
  • Freertos低功耗管理

    空闲任务中的低功耗Tickless处理 在整个系统运行得过程中 其中大部分时间都是在执行空闲任务的 空闲任务之所以执行 因为在系统中的其他任务处于阻塞或者被挂起时才会执行 因此可以将空闲任务的执行时间转换成低功耗模式 在其他任务解除阻塞而准
  • for循环延时时间计算

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 之前做led点亮的实验 好像是被delay函数影响了 因为delay参数设置的不对
  • 特殊寄存器

    特殊寄存器 文章目录 前言 一 背景 二 2 1 2 2 总结 前言 前期疑问 STM32特殊寄存器到底是什么 特殊寄存器怎么查看和调试代码 本文目标 记录和理解特殊寄存器 一 背景 最近在看ucosIII文章是 里面提到特殊寄存器 这就进
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • 嵌入式 C++11 代码 — 我需要 volatile 吗?

    采用 Cortex M3 MCU STM32F1 的嵌入式设备 它具有嵌入式闪存 64K MCU固件可以在运行时重新编程闪存扇区 这是由闪存控制器 FMC 寄存器完成的 所以它不像a b那么简单 FMC 获取缓冲区指针并将数据刻录到某个闪存
  • 使用 STM32 USB 设备库将闪存作为大容量存储设备

    我的板上有这个闪存IC 它连接到我的STM32F04 ARM处理器 处理器的USB端口可供用户使用 我希望我的闪存在通过 USB 连接到 PC 时被检测为存储设备 作为第一步 我在程序中将 USB 类定义为 MSC 效果很好 因为当我将主板
  • STM32 传输结束时,循环 DMA 外设到存储器的行为如何?

    我想问一下 在以下情况下 STM32 中的 DMA SPI rx 会如何表现 我有一个指定的 例如 96 字节数组 名为 A 用于存储从 SPI 接收到的数据 我打开循环 SPI DMA 它对每个字节进行操作 配置为 96 字节 是否有可能

随机推荐

  • 面试后HR让你等通知的真相

    面试后 xff0c 被HR告知 回去等通知 是大多数求职者会遇到的情况 前程无忧论坛曾经有过的调查显示 xff0c 在众多面试答复中 xff0c 求职者最痛恨的就是这个答复 求职者心声 xff1a 要还是不要 xff0c 给个痛快 xff0
  • 女程序员过三奔四,你的名字是迷茫???/孩子是我幸福的源泉

    Leo 博客 周一 周五固定更新 我的邮箱 xff1a Careerdesign 64 foxmail com 上次讲的是我的博客点击过百万 xff0c 写了 假如生活欺骗了你 今天说说 xff0c 过三奔四的女程序员的职业规划 Leo 您
  • QT 开发---QGroundControl地面站V2.6--环境搭建(详解)

    QT 开发 QGroundControl 地面站 环境搭建 xff08 文档更新日期 xff1a 2018 05 10 xff09 1 镜像下载 QT5 4 0 首先找到中国科学技术大学镜像网址 xff1a http mirrors ust
  • 基于STM32的FreeRTOS实时操作系统1

    本开发是基于STM32CUBEIDE1 4 0 与STM32CUBEMX相同FreeRTOS的组件在 xff1a 在Interface中选择CMSIS V1 选择这个界面适合STM32的开发 xff0c 接下来选择合适的任务进行设置 对与这
  • 免费方案:Kibana 监控 windows server 服务器系统资源,内网穿透

    kibana 监控服务器 目录预览 1 需求说明 1 1 工具选择 2 metricbeat工具介绍 3 安装部署 3 1 下载 3 2 配置 3 3 安装 3 4 启动 4 验证 5 性能 6 维护 7 Troubleshooting 一
  • MAC OS X10.9.5下成功驱动独立显卡"影驰Nvidia GeForce GTX 760大将(4GB)--非公版"

    我的机器是台式机 自己组装的 xff0c 硬件参数如下 xff1a 操作系统 Windows 7 旗舰版 64位 SP1 DirectX 11 处理器 英特尔 Core i7 4770K 64 3 50GHz 四核 主板 华硕 Z87 PR
  • 结构体继承自结构体

    C 43 43 Code 功能 xff1a 结构体继承自结构体 结论 xff1a 1 结构体可以继承自结构体 2 结构体同样有构造函数和析构函数 include lt iostream gt using namespace std stru
  • 【STM32L4】FreeRTOS消息队列三串口接收发送

    环境 STM32L476G DISCO 开发板STM32CubeIDE 1 1 0STM32CubeMX 5 4 0 STM32CubeIDE配置 移植FreeRTOS xff0c 选择CMSIS V2 FreeRTOS的所有配置的选择默认
  • OpenCV如何获取视频当前的一帧图像

    xff08 OpenCV读取视频 OpenCV提取视频每一帧 每一帧图片合成新的AVI视频 xff09 CvCapture 是视频获取结构 被用来作为视频获取函数的一个参数 比如 CvCapture cap IplImage cvQuery
  • 无人机、无人车仿真器AirSim中激光雷达Lidar设置

    1 在车辆或无人机中激活激光雷达 默认情况下 xff0c 激光雷达是不开启的 xff0c 如果需要开启激光雷达 xff0c 则需要在settings jason文件中进行激活 xff0c settings jason 文件位于 Docume
  • 软件项目产品化之路

    软件项目产品化之路 2 产品化之路 2 1 困惑 软件项目产品化是大量软件企业 xff0c 特别是应用型软件研发企业所必须面临的问题 不论是小型的软件公司和中大型的软件企业 xff0c 在面对软件项目和软件产品 xff0c 都有诸多困惑 到
  • 软件产品化的一些见解

    软件产品化的定义 软件产品化 即客户无需为软件添加或调整代码和语句即能完成软件的安装配置 应用初始化 系统管理 用户使用的全过程 并且软件至少能满足80 以上的用户某一组应用需求 软件产品化只是完成了产品的生产环节 后面的产品销售 市场推广
  • 程序员与工匠精神

    前几天和一个朋友聊天时说 xff1a 我有强迫症 xff0c 每次看到不符合自己审美的代码时 xff0c 总想重构一下 朋友的观点与大多数人相仿 xff0c 程序只要满足要求 xff0c 运行正确就可以 在现实的工作中一样 xff0c 每当
  • linux 进程线程思维导图

  • 修改结构体中成员的值

    include lt iostream gt using namespace std struct student char name 10 float grade 更改student数据的grade成员 xff0c 参数形式为引用 voi
  • C++中冒号的用法

    1 冒号 xff08 xff09 用法 xff08 1 xff09 表示机构内位域的定义 xff08 即该变量占几个bit空间 xff09 typedef struct XXX unsigned char a 4 unsigned char
  • C/C++预处理指令

    本文主要记录了C C 43 43 预处理指令 xff0c 常见的预处理指令如下 xff1a 空指令 xff0c 无任何效果 include包含一个源代码文件 define定义宏 undef取消已定义的宏 if如果给定条件为真 xff0c 则
  • STM32F1常用外设介绍(超详细35000字介绍)

    STM32学习笔记 GPIO配置步骤 步骤 xff1a 第一步 xff0c 使用RCC开启GPIO的时钟 第二步 xff0c 使用GPIO Init 函数初始化GPIO 第三步 xff0c 使用输出或者输入的函数控制GPIO口 常用的RCC
  • MFC拷贝文件及进度条显示

    参考 xff1a 封装CopyFileEx函数 xff0c 实现文件复制中的暂停 xff0c 控速 xff0c 获取进度 http blog csdn net career2011 article details 6844513 实例讲解C
  • 什么是寄存器?(STM32)

    什么是寄存器 xff1f 我们现在在开发STM32时 xff0c 已经很少用到寄存器编程 xff0c 更多的使用ST公司所提供的标准库和最新的HAL库进行编程实现 xff0c 但是不管是标准库还是HAL库都是在原来的寄存器层面上进行了封装