STM32二刷学习笔记--GPIO

发布于:2024-12-20 ⋅ 阅读:(10) ⋅ 点赞:(0)

GPIO使用详解

在STM32开发中,GPIO(通用输入输出)是与外设接口的基础模块。通过GPIO,我们可以连接各种外部设备,如LED、按键、传感器等。

GPIO基本结构

在这里插入图片描述
第一次看这幅图的时候琢磨了很久,难搞的要死,极度劝退. 实际上,不要全看, 只要看一条条通道即可. 然后逐渐删除即可GPIO的基本结构包括输入输出电路、上拉/下拉电阻以及一些保护电路。

  1. 保护二极管:用于防止电压过高或过低时对GPIO引脚造成损坏。
  2. 上拉/下拉电阻:用于确保输入引脚在没有外部信号时能保持稳定电平。上拉电阻将输入引脚拉高,而下拉电阻则将输入引脚拉低。
  3. 输入缓冲器:将引脚的电压信号转化为数字信号,防止电压不稳定。
  4. 输出控制(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;
}

网站公告

今日签到

点亮在社区的每一天
去签到