GPIO寄存器详解与点亮LED
GPIO简介
全称: general purpose input output,通用I/O口 \text{general purpose input output,通用I/O口} general purpose input output,通用I/O口
GPIO和引脚的区别:
不是所有的I/O口都可以由程序控制,GPIO可以用程序控制
如何查找每一个GPIO引脚功能:
可以通过查询官方数据手册:官方数据手册指路
GPIO框图详解
对于输出操作
端口上拉/下拉寄存器 (GPIOx_PUPDR)
对应参考手册
7.4.4 GPIO port pull-up/pull-down register
用途:
配置 I/O 上拉或下拉。
00:无上拉或下拉
01:上拉
10:下拉
11:保留
上拉电阻:将一个不确定的信号(高或低电平),通过一个电阻与电源
V
C
C
\text{V}_{CC}
VCC相连,固定在高电平。
下拉电阻:将一个不确定的信号(高或低电平),通过一个电阻与地
GND
\text{GND}
GND相连,固定在低电平。
端口输出数据寄存器 (GPIOx_ODR)
对应参考手册
7.4.6 GPIO port output data register
用途:
控制输出电平0/1
端口置位/复位寄存器 (GPIOx_BSRR)
对应参考手册
7.4.7 GPIO port bit set/reset register
用途:
可以控制输出0/1
"1"有效写入:
输入1,set置1,reset置0;(BS优先级高于BR)
输入0,无任何影响
端口模式寄存器 (GPIOx_MODER)
对应参考手册
7.4.1 GPIO port mode register
用途:
用于配置 I/O 方向模式
00:输入(复位状态):即写入状态
01:通用输出模式
10:复用功能模式
11:模拟模式
端口输出类型寄存器 (GPIOx_OTYPER)
对应参考手册
7.4.2 GPIO port output type register
用途:
用于配置 I/O 端口的输出类型。
0:输出推挽(复位状态)
1:输出开漏
电路图 |
|
|
作用 |
|
|
线与功能 |
|
|
电平转换 |
|
|
线与功能:多个信号线直接连接在一起,只有当所有信号全部为高电平时,合在一起的总线为高电平;只要有任意一个或者多个信号为低电平,则总线为低电平
电平转换:方便调节输出的电平,因为输出电平完全由上拉电阻连接的电源电平决定
端口输出速度寄存器 (GPIOx_OSPEEDR)
对应参考手册
7.4.3 GPIO port output type register
用途:
配置 I/O 输出速度。
00: 2 MHz(低速)
01: 25 MHz(中速)
10: 50 MHz(快速)
11: 30 pF 时为 100 MHz(高速)
15 pF 时为 80 MHz 输出(最大速度)
对于输入操作
端口输入数据寄存器 (GPIOx_IDR)
对应参考手册
7.4.5 GPIO port input data register
用途:
控制输出电平0/1
实验部分
初始化顺序
输入的初始化顺序
GPIO输入的初始化顺序
输出的初始化顺序
GPIO输出的初始化顺序
- 确定GPIO是输入、通用输出、复用功能还是模拟输入。
(模式寄存器: MODER)
- 如果输出还要确定是推挽输出还是开漏输出
(输出类型寄存器 : OTYPER)
- 配置输出的速度
(输出速度寄存器: OSPEEDR)
- 输出的时候内部的上/下拉电阻要不要开启
(上拉/下拉寄存器: PUPDR)
- 具体要输出的内容
(置位复位寄存器: BSRR和数据输出寄存器: ODR)
实例:LED点灯
main.c
/*使用寄存器的方法点亮LED灯 */
#include "stm32f4xx.h"
/*** 主函数 ***/
int main(void)
{
/* 第一步:打开GPIOF端口时钟——RCC_AHB1ENR */
RCC_AHB1ENR |= (1<<5); /*开启 GPIOF 时钟,使用外设时都要先开启它的时钟*/
/* 第二步:配置GPIOF的输入输出状态—— MODER */
GPIOF_MODER &= ~( 0x03<< (2*6)); /*GPIOF MODER6清空*/
GPIOF_MODER |= (1<<2*6); /*PF6 MODER6 = 01b 输出模式 */
/* 第三步:确定是推挽输出还是开漏输出—— OTYPER*/
GPIOF_OTYPER &= ~(1<<1*6); /*GPIOF OTYPER6清空*/
GPIOF_OTYPER |= (0<<1*6); /*PF6 OTYPER6 = 0b 推挽模式*/
/* 第四步:配置输出的速度—— OSPEEDR */
GPIOF_OSPEEDR &= ~(0x03<<2*6); /*PF6 OSPEEDR6 = 0b 速率2MHz*/
GPIOF_OSPEEDR |= (0<<2*6); /*GPIOF PUPDR6清空*/
/*第五步:输出的时候内部的上/下拉电阻要不要开启—— PUPDR)*/
GPIOF_PUPDR &= ~(0x03<<2*6);
GPIOF_PUPDR |= (1<<2*6); /*PF6 PUPDR6 = 01b 上拉模式*/
/*第六步:具体要输出的内容—— BSRR和ODR*/
GPIOF_ODR &=~ (1<<6); /*PF6 ODR 寄存器的 pF6置0,使引脚输出低电平*/
}
// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{
}
stm32f4xx.h
/*片上外设基地址 */
#define PERIPH_BASE ((unsigned int)0x40000000)
/*总线基地址 */
#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)
/*GPIO外设基地址*/
#define GPIOF_BASE (AHB1PERIPH_BASE + 0x1400)
/* GPIOF寄存器地址,强制转换成指针 */
#define GPIOF_MODER *(unsigned int*)(GPIOF_BASE+0x00)
#define GPIOF_OTYPER *(unsigned int*)(GPIOF_BASE+0x04)
#define GPIOF_OSPEEDR *(unsigned int*)(GPIOF_BASE+0x08)
#define GPIOF_PUPDR *(unsigned int*)(GPIOF_BASE+0x0C)
#define GPIOF_IDR *(unsigned int*)(GPIOF_BASE+0x10)
#define GPIOF_ODR *(unsigned int*)(GPIOF_BASE+0x14)
#define GPIOF_BSRR *(unsigned int*)(GPIOF_BASE+0x18)
#define GPIOF_LCKR *(unsigned int*)(GPIOF_BASE+0x1C)
#define GPIOF_AFRL *(unsigned int*)(GPIOF_BASE+0x20)
#define GPIOF_AFRH *(unsigned int*)(GPIOF_BASE+0x24)
/*RCC外设基地址*/
#define RCC_BASE (AHB1PERIPH_BASE + 0x3800)
/*RCC的AHB1时钟使能寄存器地址,强制转换成指针*/
#define RCC_AHB1ENR *(unsigned int*)(RCC_BASE+0x30)