STM32 GPIO其他少见的库函数解析
一,
void GPIO_DeInit(GPIO_TypeDef* GPIOx);先看一下这个函数,我们可以看到这个函数的参数是一个GPIO组的参数(GPIOB,GPIOC,GPIOA,,,,),
那我们进入标准外设库这个函数定义里面,可以看到
void GPIO_DeInit(GPIO_TypeDef* GPIOx)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));if (GPIOx == GPIOA){RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, ENABLE);RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, DISABLE);}else if (GPIOx == GPIOB){RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, ENABLE);RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, DISABLE);}else if (GPIOx == GPIOC){RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, ENABLE);RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, DISABLE);}。。。。。。。。。。。。}
}功能说明:
这个函数的作用是:
将指定的 GPIO 端口(如 GPIOA、GPIOB…)恢复到上电默认状态。
也就是说:
- 清除该端口之前的所有配置(输入/输出模式、上拉/下拉、复用功能、输出值等);
- 让它的寄存器值回到复位默认值(Reset Value)。
相当于“把这个 GPIO 重新初始化前清空一次”。
关键:用 RCC 外设复位功能清除配置
在 STM32 中,所有外设(包括 GPIO)都连接到 RCC(时钟控制器)。
RCC 有一个很重要的功能:
可以通过设置复位位来“软复位”任意外设。
比如:
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, ENABLE)
表示:让 GPIOA 进入复位状态;- 然后再执行
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, DISABLE)
表示:退出复位状态。
这个“复位-释放”操作,就会让 GPIOA 寄存器清零,恢复成出厂默认值。
所以这个函数我们用到的很少。
二
void GPIO_StructInit(GPIO_InitTypeDef*GPIO_InitStruct);参数是一个结构体指针参数,我们接着去标准外设库这个函数定义
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)
{/* Reset GPIO init structure parameters values */GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All;GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN;GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStruct->GPIO_OType = GPIO_OType_PP;GPIO_InitStruct->GPIO_PuPd = GPIO_PuPd_NOPULL;
}GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All;
意思是:
默认选择所有引脚(Pin0~Pin15)。
也就是说,默认结构体里认为“我想配置整个端口的所有引脚”,但实际上,你可以在使用前自己修改它,比如:
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5; // 只配置PA5引脚GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN;
默认模式是:
输入模式(Input Mode)。
STM32 的 GPIO 模式主要有以下几种:
| 模式 | 含义 |
|---|---|
| GPIO_Mode_IN | 输入模式 |
| GPIO_Mode_OUT | 推挽输出 |
| GPIO_Mode_AF | 复用功能(如USART、SPI) |
| GPIO_Mode_AN | 模拟输入(ADC用) |
默认用输入模式,是为了安全起见(防止意外输出造成短路或干扰)。
GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz;
设置默认的引脚输出速度为:
2MHz(低速模式)
这对应的是 GPIO 输出信号的切换速度。不同速度对应不同功耗和干扰水平:
| 参数 | 速度 | 特点 |
|---|---|---|
| GPIO_Speed_2MHz | 低速 | 功耗低、干扰小(默认) |
| GPIO_Speed_25MHz | 中速 | 兼顾一般外设使用 |
| GPIO_Speed_50MHz | 高速 | 适合高速通讯口(SPI等) |
| GPIO_Speed_100MHz | 超高速 | 用于时钟或高速外设线 |
GPIO_InitStruct->GPIO_OType = GPIO_OType_PP;
设置输出类型为:
推挽输出(Push-Pull)
推挽输出的特点是:
- 能够主动输出高电平或低电平;
- 驱动能力强。
另一种类型是开漏输出(Open-Drain),用于I²C总线等需要多设备共享线的场合。
GPIO_InitStruct->GPIO_PuPd = GPIO_PuPd_NOPULL;
设置上下拉为:
无上下拉(No Pull-up or Pull-down)
STM32 的输入引脚是“高阻态”的,如果不设置上拉或下拉,电平可能会漂浮不定(悬空)。
可选项如下:
| 参数 | 功能 |
|---|---|
| GPIO_PuPd_NOPULL | 不使用内部上拉/下拉 |
| GPIO_PuPd_UP | 上拉 |
| GPIO_PuPd_DOWN | 下拉 |
使用场景举例
在实际应用中,通常这样使用:
GPIO_InitTypeDef GPIO_InitStructure;
/* 先调用结构体初始化函数,填充默认值 */
GPIO_StructInit(&GPIO_InitStructure);
/* 再根据需求修改部分字段 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 最后应用到具体端口 */
GPIO_Init(GPIOA, &GPIO_InitStructure);这样可以避免忘记初始化结构体中某些字段,减少程序错误。
三,
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{__IO uint32_t tmp = 0x00010000;/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Pin));tmp |= GPIO_Pin;/* Set LCKK bit */GPIOx->LCKR = tmp;/* Reset LCKK bit */GPIOx->LCKR = GPIO_Pin;/* Set LCKK bit */GPIOx->LCKR = tmp;/* Read LCKK bit*/tmp = GPIOx->LCKR;/* Read LCKK bit*/tmp = GPIOx->LCKR;背景原理 — GPIO 锁定机制
STM32 的每个 GPIO 端口都有一个专门的寄存器:
GPIOx_LCKR(Lock Register)
作用:
当你锁定后,这个引脚的模式、上下拉、输出类型、速度等配置都会被冻结。
即使你后面再调用 GPIO_Init() 或者直接写寄存器,也无法修改!
必须复位 MCU 才能重新解锁。
所以这个函数就是将某个指定的GPIO引脚锁定,用的很少
四
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF);一、函数作用概述
GPIO_PinAFConfig() 用于给某个 GPIO 引脚选择外设复用功能(Alternate Function)。简单来说,STM32 的引脚都很“多才多艺”,
一个引脚既可以当普通 IO,也可以挂到各种外设上去。
比如:
| 引脚 | 可选功能 |
|---|---|
| PA9 | 普通输出 / USART1_TX / TIM1_CH2 / ... |
| PB6 | GPIO / I2C1_SCL / TIM4_CH1 / USART1_TX / ... |
GPIO_PinAFConfig() 就是告诉芯片:
“喂,PA9 你现在不当GPIO了,你去当USART1_TX吧!”
二、函数原型解析
voidGPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF);| 参数 | 说明 |
|---|---|
| GPIOx | 要配置的端口(如 GPIOA、GPIOB...) |
| GPIO_PinSource | 引脚编号(0~15,对应 Pin0~Pin15) |
| GPIO_AF | 选择的复用功能编号(AF0 ~ AF15) |
三、STM32 复用功能结构图
每个引脚的功能由寄存器控制:
GPIOx_AFRL 寄存器 → 控制 Pin0~Pin7
GPIOx_AFRH 寄存器 → 控制 Pin8~Pin15每个引脚占 4 位(bits)来选择 AF 功能号:
| AF值 | 外设功能(不同型号略有差异) |
|---|---|
| AF0 | 系统功能(如 MCO、RTC、SWD) |
| AF1 | TIM1 / TIM2 |
| AF2 | TIM3 / TIM4 / TIM5 |
| AF3 | TIM8 / TIM9 / TIM10 / TIM11 |
| AF4 | I2C1 / I2C2 / I2C3 |
| AF5 | SPI1 / SPI2 |
| AF6 | SPI3 / I2S |
| AF7 | USART1 / USART2 |
| AF8 | USART6 / UART4 / UART5 |
| AF9 | CAN1 / CAN2 / TIM12 / TIM13 / TIM14 |
| AF10 | OTG_FS / OTG_HS |
| AF11 | Ethernet |
| AF12 | FSMC / SDIO / OTG_HS |
| AF13 | DCMI |
| AF14 | 未定义 |
| AF15 | EVENTOUT |
完整的复用配置流程
假设我们要用 PA9 作为 USART1_TX:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
// 开GPIO时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
// 模式改为复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF7_USART1);
这两步缺一不可:
GPIO_Mode_AF—— 把口切换成复用模式;GPIO_PinAFConfig()—— 告诉它复用给谁。
