STM32 GPIO基础知识解析
目录
GPIO的4种输入模式:
浮空输入:
上拉输入:
下拉输入:
模拟输入:
GPIO的4种输出模式:
开漏输出:
开漏复用输出:
推挽输出:
推挽复用输出:
推挽输出与开漏输出不同之处:
4种输出速度:
控制GPIO的寄存器:
GPIO配置常用函数:
初始化函数:
2个读取输入电平函数:
2个读取输出电平函数:
4个设置输出电平函数:
GPIO初始化配置:
GPIO的4种输入模式:
GPIO_Mode(模式) | GPIO_Mode_IN | GPIO_Mode_IN | GPIO_Mode_IN | GPIO_Mode_AN |
GPIO_PuPd |
GPIO_PuPd_UP | GPIO_PuPd_DOWN | GPIO_PuPd_NOPULL |
GPIO_PuPd_NOPULL |
输入模式 | 上拉输入 | 下拉输入 | 浮空输入 | 模拟输入 |
*(在模拟输入模式下,通常需要禁用GPIO引脚上的上下拉电阻,以避免对模拟信号的干扰)*
浮空输入:
是指GPIO引脚没有被连接到高电平或低电平信号源,GPIO引脚不呈现高低电平状态。
CPU读取IO口的电平状态时,当IO口输入高/低电平时,CPU会读取到相对应的高低电平。当IO口无输入时,此时IO口电平处在一个动态变化的状态,电平保持在一种未定义的状态,既不是高电平也不是低电平。
应用说明:浮空输入模式的电平会完全取决于外部电路而与内部电路无关。常用于开关、按键、感应传感器的输出电平读取。但是在没有外部电路接入的时候,会导致IO脚浮空会使得电平不确定。
上拉输入:
上拉输入是指GPIO的引脚通过一个上拉电阻与正电源相连接,GPIO引脚保持高电平状态。
当IO口无外部输入的时候,IO口的电平稳定在高电平,则当IO口输入高电平时就无法判断是否有高电平输入。当IO口输入低电平时,就能稳定读取到低电平。
下拉输入:
下拉输入是指输GPIO的引脚通过一个下拉电阻与地相连接,GPIO引脚保持低电平状态。
当IO口无外部输入的时候,IO口的电平稳定在低电平,则当IO口输入低电平时就无法判断是否有低电平输入。当IO口输入高电平时,就能稳定读取到高电平。
应用说明:上/下拉输入经常用于按钮、开关等外部设备的输入接口。当外部设备未激活时,引脚保持在逻辑高电/低平状态,一旦外部设备产生逻辑高/低电平信号,就会被及时检测到。可以有效抗干扰,提高了输入的稳定性,避免了信号的抖动和误判。
模拟输入:
模拟输入是指将连续变化的物理量(如电压或电流)转换为数字信号,通过模拟-数字转换器(ADC)输入到CPU中。此时CPU要读取IO口的模拟信号,就不能使用浮空,上下拉输入,这三种输入模式输入的是数字信号(及输入高低电平1和0),只有设置为模拟输入才能读取IO口连续变化的的电压或电流数值。
应用说明:其优势在于可以传输连续变化的物理量,可以提供更加精细的信息。模拟输入通常应用于传感器等应用场合,可以提供高精度的测量和控制。
GPIO的4种输出模式:
GPIO_Mode (模式) |
GPIO_Mode_OUT | GPIO_Mode_OUT | GPIO_Mode_AF | GPIO_Mode_AF |
GPIO_OType | GPIO_OType_OD | GPIO_OType_PP | GPIO_OType_OD | GPIO_OType_PP |
输出模式 | 开漏输出 | 推挽输出 | 复用开漏输出 | 复用推挽输出 |
开漏输出:
CPU输出1(高电平)时,此时IO口的输出不受CPU输出的影响,而是取决于IO端口处于上拉还是下拉,若处于上拉IO口输出1(高电平),下拉输出0(低电平),同时IO口的输出状态还可以被CPU读取。
CPU输出0(低电平)时,此时IO口的输出由CPU输出决定,及IO口输出0(低电平),且不受IO口的上拉下拉影响,同时IO口的输出状态还可以被CPU读取。
应用说明:开漏输出不能直接输出高电平,能直接输出低电平,因此需要外部上拉电阻来确保输出高电平。常用于实现共享总线、电平转换或与其他开漏输出引脚连接的场景。通过连接一个上拉电阻,可以实现多个开漏输出引脚的共享,其中只有一个引脚处于拉低状态,其他引脚则处于高阻抗状态。这有助于减少冲突,实现多个设备之间的通信或协同工作。
开漏复用输出:
开漏复用输出与开漏输出的唯一区别在于输出信号的来源,开漏复用输出的信号来源于外设模块,开漏输出的信号来源于CPU。
推挽输出:
CPU输出1/0(高低电平)时,此时IO口的输出由CPU输出的信号决定,同时IO口的输出状态还可以被CPU读取。
CPU输出1(高电平)时,输出引脚被拉高至电源电压(相当于引脚上拉),输出高电平。
CPU输出0(低电平)时,输出引脚被拉低至地(相当于引脚下拉),输出低电平。
应用说明:推挽输出具有较强的驱动能力,可以直接驱动负载而无需外部元件。这种输出模式适用于驱动各种逻辑电路、外围设备或其他数字电路。
推挽复用输出:
推挽复用输出与推挽输出的唯一区别在于输出信号的来源,推挽复用输出的信号来源于外设模块,推挽输出的信号来源于CPU。
推挽输出与开漏输出不同之处:
推挽输出与开漏输出不同之处在于,推挽输出可以主动拉高和拉低输出信号(主动输出高低电平),而开漏输出只能拉低输出信号(只能输出低电平),需要外部上拉电阻才能拉高信号线(输出高电平)。推挽输出在实际应用中更为普遍,特别适用于需要直接输出高/低电平信号并具有较强驱动能力的场合。
4种输出速度:
速度 | 2MHZ, | 25MHZ, | 50MHZ, | 100MH |
GPIO_Speed | GPIO_Low_Speed | GPIO_Medium_Speed | GPIO_Fast_Speed | GPIO_High_Speed |
控制GPIO的寄存器:
每组IO口含有10个寄存器。也就是10个寄存器共可以控制一组GPIO的16个IO口。
一个端口模式寄存器(GPIOx MODER)
一个端口输出类型寄存器(GPIOx_OTYPER)
一个端口输出速度寄存器(GPIOx_OSPEEDR)
一个端口上拉下拉寄存器(GPIOX_PUPDR)
一个端口输入数据寄存器(GPIOx_IDR)
一个端口输出数据寄存器(GPIOx_ODR)
一个端口置位/复位寄存器(GPIOx_BSRR)
一个端口配置锁存寄存器(GPIOx LCKR)
两个复位功能寄存器(低位GPIOx_AFRL & GPIOx_AFRH)
GPIO配置常用函数:
初始化函数:
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
设置GPIO端口的各种属性,如模式、速度、上拉/下拉等。
2个读取输入电平函数:
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
用于读取指定GPIO端口的输入电平,如PA0
uint8_t pinState = GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_0); // 读取PA0引脚的状态
if(pinState == 1) {
// 引脚为高电平状态
} else {
// 引脚为低电平状态
}
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
同时读取多个引脚的输入电平,PA0-15
uint16_t inputData = GPIO_ReadInputData(GPIOA); // 读取GPIOA端口的输入数据
for(int i = 0; i < 16; i++) {
if((inputData >> i) & 0x01) {
// 第i引脚为高电平状态
} else {
// 第i引脚为低电平状态
}
}
2个读取输出电平函数:
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
用于读取指定的GPIO端口的输出电平,如读取PA0的输出电平
uint8_t status = GPIO_ReadOutputDataBit(GPIOA, GPIO_PIN_0); // 读取PA0引脚的状态
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
同时读取多个引脚的输出电平,如读取PA0-15的输出电平
uint16_t data = GPIO_ReadOutputData(GPIOA); // 读取GPIOA端口的整个输出数据
4个设置输出电平函数:
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
将指定引脚设置为高电平状态,如PA0
GPIO_SetBits(GPIOA, GPIO_PIN_0); // 将PA0引脚设置为高电平状态
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
将指定引脚设置为低电平状态,如PA0
GPIO_ResetBits(GPIOA, GPIO_PIN_0); // 将PA0引脚设置为低电平状态
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
可以直接将特定GPIO引脚的状态设置为指定的值,而无需预先设置引脚模式。
GPIO_WriteBit(GPIOA, GPIO_PIN_0, Bit_SET); // 将PA0引脚设置为高电平状态
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
可以直接将整个GPIO端口的输出数据设置为指定的值,而无需逐个设置每个引脚的状态。
GPIO_Write(GPIOA, 0x00FF); // 设置GPIOA端口低8位引脚为高电平,高8位引脚为低电平
GPIO_SetBits和GPIO_WriteBit的区别:
GPIO_SetBits函数用于将指定引脚设置为高电平状态,相当于直接将引脚置为逻辑1。
GPIO_WriteBit函数则可以根据传入的BitAction BitVal参数来设置引脚的状态,既可以将引脚设置为高电平,也可以将引脚设置为低电平。
GPIO初始化配置:
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//定义结构体类型的变量
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//在stm32f4xx_rcc.h中调用时钟使能函数。
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 GPIO_Pin_10;//确定要初始化的IO口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//配置IO口的模式输出和输入,模拟和复用
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//配置输出类型:推挽或者开漏
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//设置输出速度
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//配置IO为上拉或者下拉或者浮空
GPIO_Init(GPIOF, &GPIO_InitStructure);//在stm32f4xx_gpio.h中调用GPIO初始化函数
GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);//设置IO输出高电平
}
作者:peinCK