当前位置: 首页 > article >正文

STM32的寄存器深度解析

目录

一、STM32 寄存器概述

二、寄存器的定义与作用

三、寄存器分类

1.内核寄存器

2.外设寄存器

四、重要寄存器详解

1.GPIO 相关寄存器

2.定时器相关寄存器

3.中断相关寄存器

4.RCC 相关寄存器 

五、寄存器操作方法

1.直接操作寄存器

2.使用库函数操作寄存器 

六、总结


        在嵌入式系统开发中,STM32 微控制器以其强大的性能和丰富的功能而备受青睐。而理解和掌握 STM32 的寄存器是深入学习和开发 STM32 的关键。本文将详细介绍 STM32 的寄存器,帮助读者更好地理解和应用 STM32。

一、STM32 寄存器概述

        寄存器是 CPU 内部用来存放数据的小型存储区域,具有高速存储的特点。在 STM32 中,寄存器可以暂存指令、数据和地址,为微控制器的高效运行提供了关键支持。例如,通过对特定寄存器的操作,可以实现对 GPIO(通用输入输出)端口的配置,控制外设的输入输出状态。在实际的嵌入式开发中,了解和掌握 STM32 寄存器的使用方法至关重要。它不仅可以帮助开发者实现对硬件的精确控制,还能提高程序的性能和可移植性。无论是直接操作寄存器,还是使用高级的库函数,都需要对寄存器的原理有深入的理解。

二、寄存器的定义与作用

        寄存器是一种有限存贮容量的高速存贮部件,在 STM32 微控制器中,它作为 CPU 内部的小型存储区域,起着至关重要的作用。寄存器可以暂存指令、数据和地址,就像一个特殊的地址存放数据的地方。例如,存放数据的寄存器可以直接存储某个引脚的高低电平数据,当需要读取这个数据时,就可以直接到这个寄存器所在的地方询问数据是多少。不同的数据会存放在不同的寄存器中,通过地址来区分这些寄存器,就像不同的行李寄存处在不同的店铺号一样。

        指令、地址寄存器与数据寄存器类似,里面存放的都是 0 和 1,在特定的规定下,数据寄存器里面存放的 0 和 1 表示数据,指令寄存器里存放的表示指令。可以把寄存器类比为有特殊功能的地方,既然是个地方当然就有地址了,所以,可以把寄存器想象为特殊的地址。比如厨房可以类比为寄存器,负责做饭这个特殊功能;仓库也是个寄存器,负责存东西这个特殊功能。需要某些功能的时候,就要操作某个寄存器。

三、寄存器分类

1.内核寄存器

  • 通用目的寄存器:用于存储数据和地址,参与算术逻辑运算等操作。在 STM32 中,通用目的寄存器包括 R0-R15 等。其中 R0-R7 是低组寄存器,所有指令都能访问;R8-R12 是高组寄存器,16 位指令不能访问,32 位指令不受限制。
  • 堆栈指针寄存器(R13):每一种异常模式(如中断等)都有其自己独立的 R13,通常指向异常模式所专用的堆栈。不同的模式下都有各自独立的堆栈,用于在程序执行过程中保存临时数据、局部变量等,保证各种模式下程序的状态的完整性。
  • 连接寄存器(R14):保存子程序返回地址。当使用 BL 或 BLX 指令进行跳转时,跳转指令自动把返回地址放入 R14 中,子程序通过把 R14 复制到程序计数器 PC 来实现返回。当异常发生时,异常模式的 R14 用来保存异常返回地址。
  • 程序计数器(R15):存放正在执行的指令的地址。在读取时,返回的值是当前指令的地址加上一定的偏移量(这与处理器的架构和流水线设计有关);向 PC 中写数据,会引起一次程序的分支。

2.外设寄存器

  • 控制寄存器(xxx_CR):用来控制、配置外设的工作方式,例如 GPIO 端口模式寄存器(GPIOx_MODER),可以配置 GPIO 引脚为输入、输出、模拟等不同的工作模式。
  • 状态寄存器(xxx_SR):存储了当前外设的工作状态,例如串口的状态寄存器(USART_SR),可以通过读取该寄存器的某些位来判断串口是否发送完成、是否接收到数据等。
  • 数据寄存器(xxx_DR):用于存储外设进行输入输出的数据。比如 GPIO 端口的输入数据寄存器(GPIOx_IDR)用于读取 GPIO 引脚的输入状态,输出数据寄存器(GPIOx_ODR)用于设置 GPIO 引脚的输出状态。
  • 位操作寄存器:针对某些需要对单个位进行操作的场景,STM32 提供了位操作寄存器。例如 GPIOx_BSRR(设置 / 清除寄存器),可以对 GPIO 引脚的单个位进行置位和复位操作,方便了对特定引脚位的控制,而不必对整个寄存器进行操作。
  • 锁定寄存器:用于锁定某些寄存器的配置,防止意外的修改。比如 GPIO 端口配置锁定寄存器(GPIOx_LCKR),可以在配置完成后锁定 GPIO 的配置,避免误操作改变引脚的配置。

四、重要寄存器详解

1.GPIO 相关寄存器

  • GPIO 端口模式寄存器(GPIOx_MODER)
    • 功能:用于配置 GPIO 引脚的工作模式,如输入、输出、模拟、复用等模式。
    • 位定义:每两位控制一个引脚的模式,比如 00 表示输入模式,01 表示输出模式,10 表示模拟模式,11 表示复用功能模式。
    • 举例:若要将 GPIOA 的引脚 5 配置为输出模式,需要将 GPIOA_MODER 寄存器的第 10、11 位设置为 01。
  • GPIO 端口输出类型寄存器(GPIOx_OTYPER)
    • 功能:配置 GPIO 引脚的输出类型是推挽输出还是开漏输出。
    • 位定义:每一位对应一个引脚,0 表示输出推挽(复位状态),1 表示输出开漏。
    • 举例:将 GPIOA_OTYPER 的第 5 位设置为 1,可将 GPIOA 的引脚 5 配置为开漏输出。
  • GPIO 端口输出速度寄存器(GPIOx_OSPEEDR)
    • 功能:设定 GPIO 引脚的输出速度,速度越快,功耗越高,但信号传输速度也越快。
    • 位定义:每两位控制一个引脚的输出速度,00 表示 2MHz(低速),01 表示 25MHz(中速),10 表示 50MHz(快速),11 表示 30pF 时为 100MHz(高速,15pF 时为 80MHz 输出最大速度)。
    • 举例:若要将 GPIOA 的引脚 3 的输出速度设置为快速,需将 GPIOA_OSPEEDR 寄存器的第 6、7 位设置为 10。
  • GPIO 端口上拉 / 下拉寄存器(GPIOx_PUPDR)
    • 功能:配置 GPIO 引脚的上拉或下拉状态,用于在输入模式下确保引脚的默认电平状态。
    • 位定义:每两位控制一个引脚,00 表示无上拉或下拉(浮空),01 表示上拉,10 表示下拉,11 为保留。
    • 举例:将 GPIOA_PUPDR 的第 4 位设置为 01,可将 GPIOA 的引脚 4 配置为上拉输入。
  • GPIO 端口输入数据寄存器(GPIOx_IDR)
    • 功能:该寄存器为只读寄存器,用于读取 GPIO 引脚的输入电平状态。
    • 位定义:每一位对应一个引脚,读取该位的值为 0 或 1,分别表示对应引脚的低电平或高电平。
    • 举例:读取 GPIOA_IDR 寄存器的值,可以获取 GPIOA 所有引脚的输入电平状态。
  • GPIO 端口输出数据寄存器(GPIOx_ODR)
    • 功能:可通过软件读写该寄存器来设置 GPIO 引脚的输出电平,写入 0 为低电平,写入 1 为高电平。
    • 位定义:每一位对应一个引脚的输出状态。
    • 举例:向 GPIOA_ODR 寄存器的某一位写入 1,可将对应引脚设置为高电平输出。
  • GPIO 端口置位 / 复位寄存器(GPIOx_BSRR)
    • 功能:用于对 GPIO 引脚进行置位或复位操作,操作方式简单快速,无需通过修改 GPIOx_ODR 寄存器来实现。
    • 位定义:寄存器的高 16 位为复位位,低 16 位为置位位。写入 1 到相应的位可对引脚进行操作,写入 0 则无操作。
    • 举例:要将 GPIOA 的引脚 2 置位,可向 GPIOA_BSRR 寄存器的第 2 位(低 16 位中的第 2 位)写入 1;要将引脚 7 复位,可向 GPIOA_BSRR 寄存器的第 7 位(高 16 位中的第 7 位)写入 1。
  • GPIO 端口配置锁定寄存器(GPIOx_LCKR)
    • 功能:用于锁定 GPIO 的配置,防止意外的修改。
    • 位定义:第 16 位为锁定键,写入特定的序列可激活锁定功能;第 0 - 15 位为锁定位,用于指定哪些引脚的配置被锁定。
    • 举例:按照锁定键写序列操作 GPIOx_LCKR 寄存器,可锁定 GPIO 引脚的配置。

2.定时器相关寄存器

  • 自动装载寄存器(TIMx_ARR)
    • 功能:决定了定时器的计数周期。当定时器的计数器达到 ARR 的值时,会产生更新事件,可用于触发中断或 DMA 请求等操作。
    • 工作模式:分为自动装载寄存器缓冲寄存器和自动装载寄存器影子寄存器。通过 ARPE 位控制缓冲寄存器的数据何时更新到影子寄存器。当 ARPE = 0 时,写 ARR 时数据直接写入影子寄存器;当 ARPE = 1 时,只有更新事件发生时,缓冲寄存器的数据才更新到影子寄存器。
    • 举例:若要设置定时器的周期为 1000 个计数单位,可将 TIMx_ARR 的值设置为 999(从 0 开始计数到 999 为 1000 个计数单位)。
  • 预分频器控制寄存器(TIMx_PSC)
    • 功能:对定时器的时钟源进行分频,以降低定时器的计数频率。
    • 工作模式:也分为预分频器缓冲寄存器和预分频器影子寄存器。更新事件发生时,缓冲寄存器的内容更新到影子寄存器中。
    • 举例:如果将 TIMx_PSC 的值设置为 999,且定时器的时钟源频率为 72MHz,那么经过预分频器后,定时器的计数频率为 72MHz / (999 + 1) = 72kHz。
  • 控制寄存器(TIMx_CR1 等)
    • 功能:包含定时器的各种控制位,如定时器的使能位、计数模式(向上计数、向下计数、中心对齐计数等)选择位、更新中断使能位等。
    • 位定义:不同的位具有不同的功能,通过对这些位的设置来控制定时器的工作状态。
    • 举例:设置 TIMx_CR1 寄存器的 CEN 位为 1,可使能定时器开始计数。

3.中断相关寄存器

  • 中断使能寄存器(NVIC_ISER 等)
    • 功能:用于使能相应的中断。STM32 有多个中断源,每个中断源都有对应的使能位在中断使能寄存器中。
    • 位定义:例如在 NVIC_ISER[0] 寄存器中,每一位对应一个中断号,写入 1 使能该中断,写入 0 禁止该中断。
    • 举例:要使能外部中断线 0 的中断,需要将 NVIC_ISER[0] 的第 0 位设置为 1。
  • 中断优先级寄存器(NVIC_IPR 等)
    • 功能:设置中断的优先级。STM32 支持多个中断优先级,通过对这些寄存器的设置可以确定不同中断的优先级顺序,高优先级的中断可以打断低优先级的中断执行。
    • 位定义:每个中断号都有对应的 4 位用于设置优先级,数值越小优先级越高。
    • 举例:将某个中断的优先级设置为较高优先级,可将其在 NVIC_IPR 寄存器中对应的 4 位设置为较小的值。

 

4.RCC 相关寄存器 

  • 时钟控制寄存器(RCC_CR)
    • 功能:用于开启或关闭 STM32 的各种时钟源,如高速外部时钟(HSE)、高速内部时钟(HSI)、低速外部时钟(LSE)、低速内部时钟(LSI)等,以及配置时钟的相关参数,如时钟的分频系数等。
    • 位定义:不同的位对应不同的时钟源和参数设置,通过对这些位的操作来控制时钟的状态。
    • 举例:要开启 HSE 时钟,需要将 RCC_CR 寄存器的 HSEON 位设置为 1。
  • 时钟配置寄存器(RCC_CFGR)
    • 功能:用于配置系统时钟的来源以及各种分频系数,如 AHB、APB1、APB2 等总线的分频系数,以确定不同外设的时钟频率。
    • 位定义:通过设置寄存器中的不同位来选择系统时钟源(如 HSE、HSI 等)以及设置分频系数。
    • 举例:若要将系统时钟设置为 HSE 经过分频后作为系统时钟,需要在 RCC_CFGR 寄存器中进行相应的设置。

 

五、寄存器操作方法

1.直接操作寄存器

  • 通过指针直接访问寄存器地址,进行读写操作。这种方法需要对寄存器地址有准确的了解,并且需要注意数据类型的匹配。
  • 例如:
#define GPIOA_BASE (0x40020000UL)
#define GPIOA_MODER (*(volatile uint32_t *)(GPIOA_BASE + 0x00))

void setup_gpio()
{
    GPIOA_MODER |= (1 << 10); // 设置 GPIOA 引脚 5 为输出模式
}

2.使用库函数操作寄存器 

  • STM32 提供了丰富的库函数,可以方便地对寄存器进行操作。使用库函数可以提高开发效率,并且减少错误的发生。
  • 例如:
#include "stm32f4xx.h"

void setup_gpio()
{
    GPIO_InitTypeDef GPIO_InitStruct;

    // 使能 GPIOA 时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    // 配置 GPIOA 引脚 5 为输出模式
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
}

六、总结

STM32 的寄存器是控制微控制器功能的关键。通过对寄存器的深入理解和掌握,可以实现对 STM32 的精确控制,提高开发效率和系统性能。在实际开发中,可以根据具体需求选择直接操作寄存器或使用库函数操作寄存器。同时,需要注意寄存器的地址和数据类型的匹配,以及操作的安全性和稳定性。希望本文对读者理解和应用 STM32 的寄存器有所帮助。 


http://www.kler.cn/a/305337.html

相关文章:

  • 大数据开发面试宝典
  • ubuntu20.04安装FLIR灰点相机BFS-PGE-16S2C-CS的ROS驱动
  • python购物计算 2024年6月青少年电子学会等级考试 中小学生python编程等级考试一级真题答案解析
  • 【C++】C++11特性(上)
  • [Docker#8] 容器配置 | Mysql | Redis | C++ | 资源控制 | 命令对比
  • 040 线程池
  • Mysql的高级查询:SQL关联查询(内连接/外连接/自连接)/子查询
  • uni-app和Node.js使用uni-push2.0实现通知栏消息推送功能
  • Centos挂载和删除nfs
  • python选择排序算法
  • 基于Java+Mysql实现(web)大型企业管理系统
  • API安全测试 | Postman + BurpSuite 配置证书代理
  • chapter14-集合——(List)——day17
  • 828华为云征文|部署在线文件管理器 Spacedrive
  • 大数据-132 - Flink SQL 基本介绍 与 HelloWorld案例
  • 【LLM多模态】CogVideoX文生视频模型结构和训练过程
  • 【openGauss】检查工具gs_check,gs_checkperf的应用
  • Redisson 异步释放锁
  • 什么是485无线通信
  • 磁盘写操作压力测试工具的设计与实现
  • ChatGLM3模型搭建教程
  • OpenCV结构分析与形状描述符(20)计算一个包围给定点集的最小外接圆函数minEnclosingCircle()的使用
  • 研1日记12
  • C++系列-函数对象/仿函数
  • [网络]TCP/IP协议 之 网络层IP协议(3)
  • 艾丽卡的区块链英语小课堂