STM32学习笔记——GPIO
GPIO——General Purpose Input Output——通用输入输出出口
特点:通用性、快速翻转、中断支持、支持多种工作模式。
8种输入输出模式
模式 | 性质 | 特征 | 应用 | 标识 |
浮空输入 |
数字输入 |
可读取引脚电平,若引脚悬空,则电平不确定 |
适用于需要读取外部信号的场景,但外部信号状态不确定。 |
GPIO_Mode_IN_FLOATING |
上拉输入 |
数字输入 |
可读取引脚电平,内部连接上拉电阻,悬空时默认高电平 |
用于外部信号默认为高电平的情况,如按钮按下时会拉低信号。 |
GPIO_Mode_IPU |
下拉输入 |
数字输入 |
可读取引脚电平,内部连接下拉电阻,悬空时默认低电平 |
适用于外部信号默认为低电平的情况,如按钮按下时会拉高信号。 |
GPIO_Mode_IPD |
模拟输入 |
模拟输入 |
GPIO无效,引脚直接接入内部ADC |
适用于需要进行模拟信号处理的场景。 |
GPIO_Mode_AIN |
开漏输出 | 数字输出 |
可输出引脚电平,高电平为高阻态,低电平接VSS |
适用于需要多个输出端口共享同一信号线的场景,例如I2C的SDA、SCL线。 |
GPIO_Mode_Out_OD |
推挽输出 | 数字输出 |
可输出引脚电平,高电平接VDD,低电平接VSS |
适用于需要输出到外部设备,需要较大驱动能力的场景。 |
GPIO_Mode_Out_PP |
复用开漏输出 | 数字输出 |
由片上外设控制,高电平为高阻态,低电平接VSS |
适用于需要实现外设功能,同时共享信号线的场景,例如硬件I2C的SDA、SCL线 |
GPIO_Mode_AF_OD |
复用推挽输出 | 数字输出 | 由片上外设控制,高电平接VDD,低电平接VSS | 适用于需要实现外设功能,同时需要提供较大驱动能力的场景,例如SPI的SCK、MISO、MOSI线。 | GPIO_Mode_AF_PP |
引脚电平:0V~3.3V,部分引脚可容忍5V
GPIO的库函数位置
函数 | 解释 |
void GPIO_DeInit(GPIO_TypeDef* GPIOx) | gpio的反初始化函数,该函数的作用是把GPIO相关的寄存器配置成上电复位后的默认状态,在第一次初始化前或者不在使用某一接口后,可以调用该函数。 |
void GPIO_AFIODeInit(void) | 外设映射设置恢复为默认状态,以重新初始化外设映射配置。 |
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) | GPIO的初始化函数,该函数的作用是对io进行初始化。 |
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct) | GPIO结构体的初始化。对GPIO_InitStruct结构体进行默认配置。 |
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) | 读取io输入管脚的值 |
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx) | 读取输入io数据,该函数用于读取一个io分组的所有数据 |
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) | 读取io输出管脚的值 |
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx) | 读取输出io数据,该函数用于读取一个io分组的所有数据 |
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) | 对io管脚进行置位(输出高电平) |
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) | 对io管脚进行复位(输出低电平) |
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal) | 对某一位进行写入操作。 |
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal) | 对GPIO端口进行写入操作,适用于对统一端口的多个管脚的写入。 |
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) | 锁定GPIO寄存器,锁定的寄存器是GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR, GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH。在下一次复位前,被锁定的管脚不能被修改。 |
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) | 配置GPIO引脚作为事件输出,用于特定的事件通知机制。 |
void GPIO_EventOutputCmd(FunctionalState NewState) |
启用或禁用GPIO事件输出功能。 |
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState) | 重新映射指定引脚,以实现不同的引脚功能。(重映射和IO口的复用一样,需要开启AFIO的时钟。) |
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) | 配置外部中断线的GPIO端口和引脚。 |
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface) | 配置以太网介质接口。 |
通用外设驱动模型:
初始化→读函数→写函数→设置中断
初始化(常用):
void __GPIO_Init(void){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //RCC_APB2Periph_GPIOB-》这里选择的是STM上的B0和B10,所以是GPIOB ENABLE-》使能 GPIO_InitTypeDef GPIO_InitStructure; //定义结构体 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //输入模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_10;//端口 可同时定义多个 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //选择速率 GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化 }
STM32按键控制开关灯实例:
LED灯的配置
#include "stm32f10x.h" void LED_Init(void){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOA口的PA0、PA2、PA5端口,设置推挽输出 GPIO_SetBits(GPIOA,GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_5); //PA0、PA2、PA5端口输出高电平 } void LED1_ON(void){ GPIO_ResetBits(GPIOA,GPIO_Pin_0); } void LED1_OFF(void){ GPIO_SetBits(GPIOA,GPIO_Pin_0); } void LED2_ON(void){ GPIO_ResetBits(GPIOA,GPIO_Pin_2); } void LED2_OFF(void){ GPIO_SetBits(GPIOA,GPIO_Pin_2); } void LED3_ON(void){ GPIO_ResetBits(GPIOA,GPIO_Pin_5); } void LED3_OFF(void){ GPIO_SetBits(GPIOA,GPIO_Pin_5); } //3个LED开关灯操作,低电平点亮,高电平熄灭 void LED1_Turn(void){ if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0){ GPIO_SetBits(GPIOA,GPIO_Pin_0); }else{ GPIO_ResetBits(GPIOA,GPIO_Pin_0); } } //读取PA0端口的LED状态,进行翻转操作 void LED2_Turn(void){ if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) == 0){ GPIO_SetBits(GPIOA,GPIO_Pin_2); }else{ GPIO_ResetBits(GPIOA,GPIO_Pin_2); } } //读取PA2端口的LED状态,进行翻转操作 void LED3_Turn(void){ if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5) == 0){ GPIO_SetBits(GPIOA,GPIO_Pin_5); }else{ GPIO_ResetBits(GPIOA,GPIO_Pin_5); } } //读取PA5端口的LED状态,进行翻转操作
开关的配置
#include "stm32f10x.h" // Device header #include "Delay.h" void Key_Init(void){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化PB0和PB10端口,分别连接了两个开关,使用上拉输入模式 } uint8_t Key_GetNum(void){ uint8_t KeyNum = 0; if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0){ //读取PB0端口数据判断是否为0(低电平) Delay_ms(20); //延时过滤 while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0); //当为0时跳出循环 Delay_ms(20); //延时过滤 KeyNum = 1; //标志位置1 } if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==0){ Delay_ms(20); while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==0); Delay_ms(20); KeyNum = 2; } return KeyNum; //返回标志位 }
主函数
#include "stm32f10x.h" #include "Delay.h" #include "LED.h" #include "Key.h" uint8_t KeyNum; int main(void) { LED_Init(); //灯初始化 Key_Init(); //开关初始化 while(1){ KeyNum = Key_GetNum(); //获取标志位 if(KeyNum == 1){ LED1_Turn(); } if(KeyNum == 2){ LED2_Turn(); LED3_Turn(); } //标志位为1时,翻转LED1,为2时翻转LED2和LED3 } }