本文基于STM32F407ZGT6,适用于绝大部分M3/M4内核的STM32芯片。
———————————————————————————————
STM32每个通用 I/O 端口包括 10个32位寄存器
一、4个 32 位配置寄存器
- 1、GPIOx_MODER——用于选择 I/O 方向(输入、输出、AF(复用)、模拟)。
- 2、GPIOx_OTYPER——用于选择输出类型(推挽或开漏)(IO口设置为输入时不用设置此寄存器)
- 3、GPIOx_OSPEEDR ——用于选择输出速度(IO口设置为输入时不用设置此寄存器)
- 4、GPIOx_PUPDR——用于选择上拉/下拉
二、2 个 32 位数据寄存器
-
1、GPIOx_IDR——用于存储输入的数据,可对其进行读/写访问,一般用于读取IO口的输入电平。
-
2、GPIOx_ODR——用于存储待输出数据,可对其进行读/写访问,一般用于读取IO口的输出电平。
数据寄存器:保存了 GPIO 的输入电平 或 将要输出的电平。
三、1 个 32 位置位/复位寄存器: GPIOx_BSRR
置位/复位寄存器:控制输出IO口的电平(0或者1)
四、1 个 32 位锁定寄存器: GPIOx_LCKR
锁定寄存器:可以冻结 GPIO 控制寄存器,设置某锁定引脚后,就不能修改其配置。
五、2 个 32 位复用功能选择寄存器
- 1、GPIOx_AFRH
- 2、GPIOx_AFRL
根据应用程序的要求将某个复用功能连接到其它某个引脚。(比如把PA9 和 PA10 用作串口usart1的 Tx 和 Rx)
关于哪个引脚的具有哪些复用功能可以查看芯片的数据手册(不是中文参考手册)。
STM32的配置模式
STM32的IO口不是设置为输入就是输出,所以IO口可以设置为输入或者输出模式。
输入模式有4种:
1、上拉输入
2、下拉输入
3、浮空输入
4、模拟输入
设置为输入模式需要配置的寄存器有2个(当然你设置了其他寄存器也不会出错,只是会有点浪费单片机的资源):
- 1、GPIOx_MODER——选择 I/O 方向输入/模拟
- 2、GPIOx_PUPDR——用于选择上拉/下拉(如果是浮空输入/模拟输入模式不用设置该寄存器)
输出模式有4种:
1、具有上拉或下拉功能的开漏输出
2、具有上拉或下拉功能的推挽输出
3、具有上拉或下拉功能的复用功能推挽
4、具有上拉或下拉功能的复用功能开漏
设置为输出模式需要配置的寄存器有5个:
- 1、GPIOx_MODER——选择 I/O 方向输出/AF
- 2、GPIOx_OTYPER——选择输出类型(推挽或开漏)
- 3、GPIOx_OSPEEDR ——选择输出速度
- 4、GPIOx_PUPDR——选择输出上拉/下拉
- 5、GPIOx_AFRH/GPIOx_AFRL——仅当你使用复用功能时还需要配置复用功能选择寄存器
下面用STM32的GPIOA2、GPIOA3设置为复用输出模式的USART2为例子:
/****************** UART2模块 GPIO口配置 *************************/
//开GPIOA 口时钟,每个GPIO都要开启时钟
RCC->AHB1ENR |= 1 << 0;
//配置 GPIOA2、GPIOA3 为:复用输出模式
GPIOA->MODER &= ~(3 << 2 * 2 | 3 << 3 * 2); //对应的两位分别清0
GPIOA->MODER |= (2 << 2 * 2 | 2 << 3 * 2); //对应的两位分别设置为10
//配置GPIOA2、GPIOA3 为:输出推挽(复用状态)
GPIOA->OTYPER &= ~(1 << 2 | 1 << 3 ); //对应的位分别清0
//配置 GPIOA2、GPIOA3 速度为: 2 MHz(低速) -- 可选
GPIOA->OSPEEDR &= ~(3 << 2 * 2 | 3 << 3 * 2);
//配置 GPIOA2、GPIOA3 为:01:上拉 -- 可选
//(注意不能设置为下拉,否则可能第一次通信可能会多发一个 '?' 字符)
GPIOA->PUPDR &= ~(3 << 2 * 2 | 3 << 3 * 2); //对应的两位分别清0
GPIOA->PUPDR |= (1 << 2 * 2 | 1 << 3 * 2); //对应的两位分别设置为01
//配置为复用引用功能
GPIOA->AFR[0] &= ~(0Xf << 2 * 4);
GPIOA->AFR[0] |= (0x7 << 2 * 4);
GPIOA->AFR[0] &= ~(0Xf << 3 * 4);
GPIOA->AFR[0] |= (0x7 << 3 * 4);
//*****************************end***********************************//
总结:个人觉得用寄存器来编程虽然可以提高程序运行速率,但是这样做会导致程序编写难度太大、程序可移植性和可读性不高。所以笔者建议大家都使用库函数开发STM32,但是这并不意味着我们不需要懂寄存器,理解寄存器才能更好地理解STM32的库。