GPIO

GPIO

GPIO(General Purpose Input Output)

GPIO功能描述

STM32的GPIO模块通过软件编程实现I/O端口的重新映射,从而达到I/O端口功能的复用。

GPIO端口的每个位可以由软件分别配置成下列9个模式:

  • 浮空输入:当引脚浮空时,相当于介入高电平;
  • 上拉输入:将不确定的信号通过一个电阻嵌位在高电平;
  • 下拉输入;
  • 模拟输入;
  • 开漏输出;
  • 推挽式输出;
  • 复用功能推挽式输出;
  • 复用功能开漏输出;

GPIO的基本结构

image-20201219093142694

复用功能

使用默认复用功能前必须对端口位配置寄存器

  • 对于复用输入,端口必须配置为输入模式(浮空、上拉或下拉)且输入引脚必须由外部驱动;
  • 对于复用输出,端口必须配置为复用输出模式(推挽或开漏);
  • 对于双向复用,端口必须配置为复用输出(推挽或开漏),输入驱动器必须配置为浮空输入模式。

输入配置

当I/O端口配置为输入时:

  • 输出缓冲器被禁止;
  • 出现在I/O脚上的数据在每个APB2时钟被采样到输入数据寄存器IDR中

输出配置

  • 输出缓冲器被激活;
  • 在开漏模式时,对输入数据寄存器的读访问可得到I/O状态;
  • 出现在I/O引脚上的数据在每个ABP2时钟被采样到输出数据寄存器;
  • 在推挽模式,对输出寄存器的读访问可得到最后一次写入的值

GPIO常用库函数

  • void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

    第一个参数确定是哪个GPIO, 第二个参数设置该GPIO的引脚以及引脚的模式和输出最大速度。

    第二个参数的结构体为

    typedef struct
    {
    uint16_t GPIO_Pin;
    GPIOSpeed_TypeDef GPIO_Speed;
    GPIOMode_TypeDef GPIO_Mode;
    } GPIO_InitTypeDef;
    

    GPIO_Mode即之前提到的可配置的九种模式的一个枚举

    typedef enum
    {
    GPIO_Mode_AIN = 0x0,
     //模拟输入
    GPIO_Mode_IN_FLOATING = 0x04,
     //浮空输入
    GPIO_Mode_IPD = 0x28,
     //下拉输入
    GPIO_Mode_IPU = 0x48,
     //上拉输入
    GPIO_Mode_Out_OD = 0x14,
     //开漏输出
    GPIO_Mode_Out_PP = 0x10,
     //通用推挽输出
    GPIO_Mode_AF_OD = 0x1C,
     //复用开漏输出
    GPIO_Mode_AF_PP = 0x18
     //复用推挽
    }GPIOMode_TypeDef;
    

    函数使用示例:

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    

    GPIO_Init函数并不只是在初始化时才调用,每一次需要改变GPIO端口时都需要调用这个函数来完成。

  • uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

    读取某个GPIO的某个引脚的值,返回结果为一个8位的整型,也就是读取一个字节。下面的函数中,如果没有给出参数,说明参数与本函数一致。

    同样的还有读取输出寄存器的值的函数GPIO_ReadOutputDataBit,这里不作赘述。

  • GPIO_SetBitsGPIO_ResetBits

    置位和重置位

GPIO案例——跑马灯

跑马灯硬件连接图

image-20201219110900801

/*
 * 使用GPIO实现跑马灯
 * 库函数的包括就略了
 */
int main() {
    GPIO_InitTypeDef GPIO_InitStructure;
    delay_init();
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟
    
    //配置GPIO
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_SetBits(GPIOB, GPIO_Pin_5); //LED0配置在GPIOB pin5,pin5推挽输出
    GPIO_Init(GPIOE, &GPIO_InitStructure);//LED1配置在GPIOE pin5
    GPIO_SetBits(GPIOE, GPIO_Pin_5);

    while (1) {
        GPIO_ResetBits(GPIOB, GPIO_Pin_5);
        GPIO_SetBits(GPIOE, GPIO_Pin_5);
        delay_ms(500); //延迟500ms
        GPIO_SetBits(GPIOB, GPIO_Pin_5);
        GPIO_ResetBits(GPIOE, GPIO_Pin_5);
        delay_ms(500);
    }
}
原文地址:https://www.cnblogs.com/lunar-ubuntu/p/14162255.html