STM32之GPIO

1. 什么是GPIO

• GPIO是通用输入输出端口,是(General-purpose input output)的英文简写。是所有微控制器必不可少的外设之一,其作用是可以由STM32直接驱动从而和外界进行交互,从而实现和外界设备进行通信,控制,采集以及捕获的功能。

• GPIO口可以配置成多种工作模式,比如:浮空输入(GPIO_MODE_INPUT),推挽输出(GPIO_MODE_OUTPUT_PP),开漏输出(GPIO_MODE_OUTPUT_OD),复用推挽输出(GPIO_MODE_AF_PP),复用开漏输出(GPIO_MODE_AF_OD),复用输入(GPIO_MODE_AF_INPUT),模拟输入(GPIO_MODE_ANALOG)。

• STM32单片机中有多组GPIO口,例如:GPIOA,GPIOB等等,每组最多有16 个引脚,不同型号的单片机所拥有的GPIO口数量不同。

• STM32单片机引脚的电压为0-3.3v,部分引脚为5v。

2. GPIO内部结构

• 如图:

• 这个图来自芯片手册,这是GPIO的基本结构,这里面是分为输入和输出两种:

2.1 输入分为上拉输入,下拉输入,浮空输入,模拟输入

• 上拉输入:默认接了一个上拉电阻(VDD),如果此时GPIO口就算没有外界的输入,该引脚默认保持高电平,只有外界来了一个低电平信号,引脚才表示低电平。

• 下拉输入:默认接了一个下拉电阻(VSS),如果此时GPIO口就算没有外界的输入,该引脚默认保持低电平。只有外界来了一个高电平信号,引脚才表示高电平。

• 浮空输入:既没接上拉电阻,也没有接下拉电阻。此时浮空状态下,电平信号是不确定的,完全是由外界输入决定的,如果在浮空状态读取,电平是不确定的。

• 模拟输入:输入信号是不用经过TTL肖特基触发器,是直接接入进入的,输入信号为模拟量 ,然后经过ADC变为数字量

• TTL肖特基触发器:让读取进来的信号进行修剪,变成方波形状。

2.2 输出分为推挽输出,开漏输出,复用推挽输出,复用开漏输出

• 推挽输出:既能输出低电平也能输出高电平。在推挽输出工作模式下,P-MOS和N-MOS都工作,当输出高电平的时候,N-MOS不导通,P-MOS导通输出高电平。当输出低电平的时候,P-MOS不导通,N-MOS导通输出低电平。

• 开漏输出:只能输出低电平。在开漏输出工作模式下,只有N-MOS工作,只有N-MOS导通输出低电平。就算我们要求输出高电平它也是无效的,P-MOS不会工作。

• 复用推挽输出和复用开漏输出:都由内部外设决定使用那一种工作模式。比如i2c的时钟线和数据线使用的是复用开漏输出,还有can的tx线使用的是复用推挽输出。

3. 实操

3.1 点亮一个LED灯

cpp 复制代码
#include "sys.h"
#include "uart1.h"
#include "delay.h"
#include "led.h"


int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    led_init();                         /* LED初始化 */
//    led_on();//开灯
//    delay_ms(500);
//    led_off();//关灯
    while(1)//流水灯实验
    { 
        led1_on();
        led2_off();
        delay_ms(500);//没隔500ms闪烁
        
        led2_on();
        led1_off();
        delay_ms(500);//没隔500ms闪烁
    }
}
cpp 复制代码
#include "led.h"

void led_init(){
    GPIO_InitTypeDef gpio_init = {0};
    __HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIO时钟
    gpio_init.Mode = GPIO_MODE_OUTPUT_PP;
    gpio_init.Pin = GPIO_PIN_8 | GPIO_PIN_9;//推挽输出
    gpio_init.Pull = GPIO_PULLUP;//默认上拉
    gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB,&gpio_init);//初始化gpio
    led1_off();//关灯
    led2_off();

}

void led1_on(){
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
}

void led1_off(){
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
}


void led1_toggle(){
    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
}


void led2_on(){
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
}

void led2_off(){
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
}


void led2_toggle(){
    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
}

3.2 按键控制灯

• main.c的代码

cpp 复制代码
#include "sys.h"
#include "key.h"
#include "delay.h"
#include "led.h"


int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    led_init();                         /* LED初始化 */
    key_init();
    uint8_t key_num = 0;
    while(1)
    { 
        key_num = key_scan();//不断检测按键
        if(key_num == 1)
            led1_toggle();//翻转led1
        else if(key_num == 2)
            led2_toggle();//反转led2
    }
}

• key.c的代码

cpp 复制代码
#include "key.h"
#include "delay.h"

void key_init(){
    GPIO_InitTypeDef gpio_init = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIO时钟
    gpio_init.Mode = GPIO_MODE_INPUT;
    gpio_init.Pin = GPIO_PIN_0 | GPIO_PIN_1;//推挽输出
    gpio_init.Pull = GPIO_PULLUP;//默认上拉
    gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA,&gpio_init);//初始化gpio

}

uint8_t key_scan(){
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){//判断按键是否被按下
        //延时一段时间,在判断按键是否被按下,达到软件消抖作用
        delay_ms(10);
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){//在判断按键是否被按下
            while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET);//如果被按下,等待松开按键
            return 1;//返回按键值
        }
    }
    
    
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET){//判断按键是否被按下
        //延时一段时间,在判断按键是否被按下,达到软件消抖作用
        delay_ms(10);
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET){//在判断按键是否被按下
            while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET);//如果被按下,等待松开按键
            return 2;//返回按键值
        }
    }
    
    return 0;

}
相关推荐
宵时待雨2 小时前
STM32笔记归纳2:GPIO
笔记·stm32·嵌入式硬件
小码过河.2 小时前
设计模式——建造者模式
单片机·设计模式·建造者模式
9稳2 小时前
基于单片机的家庭安全系统设计
开发语言·网络·数据库·单片机·嵌入式硬件
π同学3 小时前
基于RT-Thread的STM32开发第十二讲SD卡篇——DFS文件系统
stm32·dfs·rtthread·sdio
一路往蓝-Anbo3 小时前
第37期:启动流程(二):C Runtime (CRT) 初始化与重定位
c语言·开发语言·网络·stm32·单片机·嵌入式硬件
longxiangam3 小时前
基于esp32p4 的掌机
单片机·嵌入式硬件
代码游侠3 小时前
ARM嵌入式开发代码实践——LED灯闪烁(C语言版)
c语言·开发语言·arm开发·笔记·嵌入式硬件·学习
Analog1113 小时前
电子秤采用 SIG5530 国产平替 CS5530
人工智能·嵌入式硬件·目标检测·硬件架构·信号处理·智能硬件
Saniffer_SH4 小时前
【高清视频】笔记本电脑出现蓝屏、死机、慢、不稳定是这样连接分析M.2 SSD的
运维·服务器·网络·人工智能·驱动开发·嵌入式硬件·fpga开发