一、寄存器是什么?

寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。其实寄存器就是一种常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。寄存器是中央处理器内的组成部分。寄存器是有限存储容量的高速存储部件,它们可用来暂存指令、数据和位址

简单来说,寄存器就是日常生活中存储东西的柜子,通过号码牌(也就是地址)来找到对应存储东西的柜子进行存储等一系列操作

如何访问寄存器?
不同的寄存器对应着不同的地址,根据所给的寄存器地址可以找到对应的寄存器,就可以进行我们的操作了。

如何获取寄存器地址?就需要我们查询数据手册了
下面通过GPIO的寻址进行阐述

二、地址映射和寄存器映射原理

存储器本身没有地址,给存储器分配地址的过程叫存储器映射,我们知道地址是连续的如果我们需要给存储器分配地址,可以将地址分为多组,将每一组地址映射给对应的存储器,这就是存储器映射

stm32f103系列存储器映射如下图:
在这里插入图片描述

什么叫寄存器映射?

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

下面通过查找GPIOB端口相关寄存器进行举例:

第一步,找到GPIOB的基地址
也就是找到GPIOB的小区。结论是,所有GPIOB相关的寄存器,都住在0x4001 0C00到0x4001 0FFF范围内。
在这里插入图片描述

第二步,找到端口输入寄存器的地址偏移
找到存储数据的地址,结论是0x4001 0C00+0x08 = 0x4001 0C08
在这里插入图片描述

第三步,找到存储数据的最终位置
PB3的数据位于从右往左数第4个。

在这里插入图片描述
我们可以简单地直接访问这个地址:

unsigned int *GPIOB_IDR=(unsigned int *)0x40010C08;
unsigned char PB3 = *GPIOB_IDR & 0x8;//取出从右往左数的第4位

GPIO初始化设置步骤(时钟配置、输入输出模式设置、最大速率设置)

1.GPIO简介

GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。STM32 芯片的 GPIO 被分成很多组,每组有 16 个引脚,如型号为 STM32F103VET6 型号的芯片有 GPIOA、GPIOB、GPIOC至 GPIOE共 5组 GPIO,芯片一共 100个引脚,其中 GPIO就占了一大部分,所有的 GPIO 引脚都有基本的输入输出功能。

最基本的输出功能
是由 STM32 控制引脚输出高、低电平,实现开关控制,如把 GPIO引脚接入到 LED灯,那就可以控制 LED灯的亮灭,引脚接入到继电器或三极管,那就可以通过继电器或三极管控制外部大功率电路的通断。

最基本的输入功能
检测外部输入电平,如把 GPIO 引脚连接到按键,通过电平高低区分按键是否被按下。

2.GPIO工作模式

GPIO框架图
在这里插入图片描述

由 GPIO 的结构决定了 GPIO 可以配置成以下模式:

GPIO 8 种工作模式:
typedef enum{
	GPIO_Mode_AIN = 0x0, // 模拟输入
 	GPIO_Mode_IN_FLOATING = 0x04, // 浮空输入
 	GPIO_Mode_IPD = 0x28, // 下拉输入
	GPIO_Mode_IPU = 0x48, // 上拉输入
	GPIO_Mode_Out_OD = 0x14, // 开漏输出
	GPIO_Mode_Out_PP = 0x10, // 推挽输出
	GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出
	GPIO_Mode_AF_PP = 0x18 // 复用推挽输出
} GPIOMode_TypeDef;

在固件库中,GPIO 总共有 8 种细分的工作模式,稍加整理可以大致归类为以下三类:

2.1 输入模式(模拟/浮空/上拉/下拉)

在输入模式时,施密特触发器打开,输出被禁止,可通过输入数据寄存器 GPIOx_IDR
读取 I/O 状态。其中输入模式,可设置为上拉、下拉、浮空和模拟输入四种。上拉和下拉
输入很好理解,默认的电平由上拉或者下拉决定。浮空输入的电平是不确定的,完全由外
部的输入决定,一般接按键的时候用的是这个模式。模拟输入则用于 ADC 采集。

2.2 输出模式(推挽/开漏)

在输出模式中,推挽模式时双 MOS 管以轮流方式工作,输出数据寄存器 GPIOx_ODR
可控制 I/O 输出高低电平。开漏模式时,只有 N-MOS 管工作,输出数据寄存器可控制 I/O
输出高阻态或低电平。输出速度可配置,有 2MHz\10MHz\50MHz的选项。此处的输出速度
即 I/O 支持的高低电平状态最高切换频率,支持的频率越高,功耗越大,如果功耗要求不
严格,把速度设置成最大即可。

在输出模式时施密特触发器是打开的,即输入可用,通过输入数据寄存器 GPIOx_IDR
可读取 I/O 的实际状态。

2.3 复用功能(推挽/开漏)

复用功能模式中,输出使能,输出速度可配置,可工作在开漏及推挽模式,但是输出信号源于其它外设,输出数据寄存器 GPIOx_ODR 无效;输入可用,通过输入数据寄存器可获取 I/O 实际状态,但一般直接用外设的寄存器来获取该数据信号。

3.GPIO初始化步骤

下面以操作寄存器来点亮LED了解GPIO初始化步骤

1. 首先配置时钟使能
时钟控制名字叫做RCC,属于AHB总线。GPIOB属于APB2。
在这里插入图片描述

由下图可知AHB总线包含RCC时钟控制,GPIO是属于APB2

在这里插入图片描述
 我们已经知道,GPIO端口B的地址从0x4001 0C00开始。接下来只寻找时钟使能寄存器的地址:
 复位和时钟控制RCC的地址从0x4002 1000开始

 
 APB2外设时钟使能寄存器(RCC_APB2ENR),偏移地址是0x18,所以APB2的地址就是0x4002 1018。
 RCC_APB2ENR,位3是IOPBEN,名字是IO端口B时钟使能,就是我们想要的。把RCC_APB2ENR的位3赋值为1,就是开启GPIOB时钟。
  在这里插入图片描述
在这里插入图片描述

2. 配置为通用输出
由于STM32的每个IO都需要4个位来配置,所以一个32位的寄存器最大只能配置8个IO,由于STM32的每个IO都需要4个位来配置,所以一个32位的寄存器最大只能配置8个IO

查看原理图可以看到点亮红色灯为PB5
在这里插入图片描述

配置引脚PB5,使用的寄存器是GPIOB_CRL。下面我们来寻找这个寄存器的地址。
在这里插入图片描述

那么需要的寄存器是低位的寄存器GPIOB_CRL,它的地址是0x4001 0c00,端口号为5
找到需要操作的寄存器后,把它配置为通用输出。 我们需要的是输出高低电平,所以要设置为输出。输出模式又有好几种输出:

00:通用推挽输出模式
01:通用开漏输出模式
10:复用功能推挽输出模式
11:复用功能开漏输出模式

由此可得:

// 开启GPIOB 端口时钟
	RCC_APB2ENR |= (1<<3);

	//清空控制PB5的端口位
	GPIOB_CRL &= ~( 0x0F<< (4*5));	
	// 配置PB5为通用推挽输出,速度为10M
	GPIOB_CRL |= (1<<4*5);

这样就把对应的IO口输入输出模式调好了

3. 设置输出值

查看GPIO输出文档(GPIOx_ODR)
在这里插入图片描述
地址偏移量0x0c,由于低电平有效所以需要将第5位设置成0,其它端口设置成1,可以实现LED的点亮

// PB5 输出 低电平
	GPIOB_ODR &= ~(1<<5);

查看结果:
在这里插入图片描述

LED点亮成功,通过点亮LED我们初步了解了GPIO的初始化

Logo

更多推荐