GPIO使用详解
在STM32开发中,GPIO(通用输入输出)是与外设接口的基础模块。通过GPIO,我们可以连接各种外部设备,如LED、按键、传感器等。
GPIO基本结构
第一次看这幅图的时候琢磨了很久,难搞的要死,极度劝退. 实际上,不要全看, 只要看一条条通道即可. 然后逐渐删除即可GPIO的基本结构包括输入输出电路、上拉/下拉电阻以及一些保护电路。
- 保护二极管:用于防止电压过高或过低时对GPIO引脚造成损坏。
- 上拉/下拉电阻:用于确保输入引脚在没有外部信号时能保持稳定电平。上拉电阻将输入引脚拉高,而下拉电阻则将输入引脚拉低。
- 输入缓冲器:将引脚的电压信号转化为数字信号,防止电压不稳定。
- 输出控制(MOSFET):控制输出引脚的电平,通过P-MOS和N-MOS来实现高电平或低电平输出。
GPIO工作模式
GPIO可以配置为多种工作模式,每种模式都有不同的应用场景。以下是常见的GPIO模式:
输入咱们只看上一条路,二极管限压不用管,触发器就是防止电压抖动,不用管,就剩下个写入数据寄存器控制输入,只有一条线是不是很简单.两个上下拉电阻用来控制模式,两个电阻都不连浮空输入引脚悬空,则电平不确定;内部连接上拉电阻,悬空时默认高电平;内部连接下拉电阻,悬空时默认低电平 .没了
输出也很简单,直接一路输出,两个寄存器都可以使用.
模式名称 | 性质 | 特征 |
---|---|---|
浮空输入 | 数字输入 | 输入引脚没有外部连接,电平不确定,易受噪声影响。 |
上拉输入 | 数字输入 | 引脚通过上拉电阻连接至VDD,输入为高电平。 |
下拉输入 | 数字输入 | 引脚通过下拉电阻连接至VSS,输入为低电平。 |
模拟输入 | 模拟输入 | 输入信号通过内部ADC进行转换,常用于传感器数据读取。 |
开漏输出 | 数字输出 | 输出为低电平时连接VSS,高电平时为高阻态,常用于I2C等通信。 |
推挽输出 | 数字输出 | 输出高电平时连接VDD,低电平时连接VSS,适合驱动LED等。 |
复用开漏输出 | 数字输出 | 外设控制的开漏输出,通常用于多设备通信,如I2C。 |
复用推挽输出 | 数字输出 | 外设控制的推挽输出,适用于高速和大电流输出。 |
简单示例
库函数本质上就是不断调用函数,先开启时钟,设置GPIO各种模式,调用输入输出模式
推挽输出LED闪烁
下面是一个简单的LED闪烁程序,它将GPIO引脚配置为推挽输出模式,使得LED每隔200ms闪烁一次。
#include "stm32f10x.h" // 设备头文件
#include "Delay.h"
int main(void)
{
/* 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 开启GPIOA时钟
/* GPIO初始化 */
GPIO_InitTypeDef GPIO_InitStructure; // 定义结构体变量
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 配置为推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 配置为引脚0
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 配置为50MHz速度
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA
/* 设置GPIO引脚的高低电平 */
while (1)
{
Delay_ms(200);
GPIO_SetBits(GPIOA, GPIO_Pin_0); // 设置为高电平
Delay_ms(200);
GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 设置为低电平
}
}
按键控制LED闪烁
以下代码演示了按键控制LED的闪烁功能。按键按下时,LED灯会开始闪烁。
#include "stm32f10x.h" // 设备头文件
#include "Delay.h"
#include "led.h"
#include "light.h"
uint8_t LightNum;
int main(void)
{
LED_Init();
LIGHT_Init();
while (1)
{
LightNum = LIGHT_GetNum(); // 获取按键状态
if (LightNum == 1)
{
LED1_Turn(); // 按键按下,切换LED状态
}
}
}
LED控制函数
# include "stm32f10x.h"
void LED_Init(void)
{
/* 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 开启GPIOA时钟
/* GPIO初始化 */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 配置为推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA
}
void LED1_On(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_2); // 关闭LED
}
void LED1_Off(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_2); // 打开LED
}
void LED1_Turn(void)
{
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == 0)
{
GPIO_SetBits(GPIOA, GPIO_Pin_2); // 打开LED
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_2); // 关闭LED
}
}
按键控制函数
# include "stm32f10x.h"
# include "Delay.h"
void KEY_Init(void)
{
/* 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 开启GPIOB时钟
/* GPIO初始化 */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 配置为上拉输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); // 初始化GPIOB
}
uint8_t KEY_GetNum(void)
{
uint8_t KeyNum = 0; // 默认键码为0
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0) // 检测按键是否按下
{
Delay_ms(20); // 延时消抖
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0); // 等待按键松开
Delay_ms(20); // 延时消抖
KeyNum = 1; // 设置按键码
}
return KeyNum;
}