STM32——GPIO设置 快速点亮第一个LED灯

首先给大家推荐一下我老师大神的人工智能教学网站。教学不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵黄段子!点这里可以跳转到网站

简介

不同的开发板的原理图结构也不尽相同,笔者在这里使用野火的MINI-V3(F103VET6)简易开发板对GPIO口的设置做一个简单的介绍,并实现按键控制LED灯的亮灭。方便读者可以快速熟悉并灵活应用。

原理图分析

首先我们来看一下发光二极管部分和按键部分的原理图。

LED原理图

下面是按键的原理图部分:

button

在这里,我们将使用KEY1(PA0)来控制红灯PB5的亮灭。由原理图可知,其控制LED灯的PB5引脚为低电平时,灯亮。当KEY1按下时,PA0引脚由之前的低电平转为高电平(3V3)。明确了目的之后我们就可以分析GPIO口并进行设置了。

GPIO设置

经过上述的功能明确之后,我们将其分为两大类,分别是输入类(如按键)和输出类(LED灯)。
STM32系列单片机的引脚有着丰富的功能,在这里将其芯片的GPIO口部分的结构图放出,有兴趣的朋友可自行研究或在评论区留言讨论。在这里笔者将不再讲解时钟树的相关内容,以免对初学者造成较大压力,有兴趣的朋友可自行参考官方文档。

GPIO结构图

输入输出模式

GPIO的输入、输出种类详见下表。

功能名称简述
输入上拉输入(GPIO_Mode_IPU)默认状态下(引脚无输入),读得的数据为1,高电平
输入下拉输入(GPIO_Mode_IPD)与上拉输入相反,默认为0,低电平
输入浮空输入(GPIO_Mode_IN_FLOATING)输入不确定,无上拉和下拉。输入阻抗较大,一般用于标准通信协议如、USART的接收端
输入模拟输入模式(GPIO_Mode_AIN)一般由ADC采集电压信号时将其设置为模拟输入。
输出普通推挽输出(GPIO_Mode_Out_PP)输出电平为3.3V
输出普通开漏输出(GPIO_Mode_Out_OD)若要输出5V,则需外加上拉电阻,电源为5V。输出为高阻态时,由上拉电阻和电源向外输出5V的高电平
输出复用推挽输出(GPIO_Mode_AF_PP)引脚复用功能采用复用模式
输出复用开漏输出(GPIO_Mode_AF_OD)复用模式,且加入上拉电阻

由上表可知,我们需要将LED灯的引脚设置为推挽输出。按键部分的输入可以是上拉输入也可以是下拉输入。在这里,因为我们的电路原理图设置的是按键按下为高,释放为低。所以我们使用下拉输入的模式 。

结构体设置

STM32以高效的库函数开发而著称。由于其寄存器过多,不适合类似51系列单片机的寄存器操作,所以我们将直接采用库函数开发的方法(CMSIS 3.5.0版本)。

STM32的库函数将结构体的功效发挥到了极致,我们首先来看一下GPIO口的结构体定义:

typedef struct {
  uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.
                                      This parameter can be any value of @ref GPIO_pins_define */

  GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.
                                      This parameter can be a value of @ref GPIOSpeed_TypeDef */

  GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.
                                      This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;

在这个结构体之中,主要包括三个成员:引脚设置(GPIO_Pin)、引脚最大输出速度(GPIO_Speed)和引脚模式(GPIO_Mode)。在这之中,GPIO还有一个重要的定义,即确定组别:GPIOA~GPIOG.
他们的种类又可以分别划分为:

  • GPIO_Speed:
    • GPIO_Speed_10MHz
    • GPIO_Speed_2MHz
    • GPIO_Speed_50MHz
  • GPIO_Mode:
    • GPIO_Mode_AIN
    • GPIO_Mode_IN_FLOATING
    • GPIO_Mode_IPD
    • GPIO_Mode_IPU
    • GPIO_Mode_Out_OD
    • GPIO_Mode_Out_PP
    • GPIO_Mode_AF_OD
    • GPIO_Mode_AF_PP
  • GPIO_Pin:
    • GPIO_Pin_0
    • GPIO_Pin_1
    • GPIO_Pin_2
    • GPIO_Pin_3
    • GPIO_Pin_4
    • GPIO_Pin_5
    • GPIO_Pin_6
    • GPIO_Pin_7
    • GPIO_Pin_8
    • GPIO_Pin_9
    • GPIO_Pin_10
    • GPIO_Pin_11
    • GPIO_Pin_12
    • GPIO_Pin_13
    • GPIO_Pin_14
    • GPIO_Pin_15

熟悉结构体类别以后我们可以进行结构体的定义以及GPIO口的初始化。由于GPIO处于APB2时钟线下,所以我们必须要开启相应的时钟。代码如下:

void key_gpio_config(void) {
    GPIO_InitTypeDef key_struct;    // 定义结构体
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // 开启时钟
    key_struct.GPIO_Pin = GPIO_Pin_0;    //结构体成员设置;对于按键初始化而言,由于GPIO是输入模式,故不必设置最大输出速度
    key_struct.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_Init(GPIOA, &key_struct);    // 初始化引脚
}

void led_gpio_config(void) {    // 同上
    GPIO_InitTypeDef led_struct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    led_struct.GPIO_Pin = GPIO_Pin_5;
    led_struct.GPIO_Speed = GPIO_Speed_50MHz;
    led_struct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOB, &led_struct);
}

自此,结构体设置结束。下面进行GPIO口的操作。

GPIO操作

对于库函数开发来说,一切硬件操作都可以使用函数来解决。如:


uint16_t  GPIO_ReadInputData (GPIO_TypeDef *GPIOx) 
  // Reads the specified GPIO input data port. 

uint8_t  GPIO_ReadInputDataBit (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 
  // Reads the specified input port pin. 

uint16_t  GPIO_ReadOutputData (GPIO_TypeDef *GPIOx) 
  // Reads the specified GPIO output data port. 

uint8_t  GPIO_ReadOutputDataBit (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 
  // Reads the specified output data port bit. 

void  GPIO_ResetBits (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 
  // Clears the selected data port bits. 

void  GPIO_SetBits (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 
  // Sets the selected data port bits. 

void  GPIO_StructInit (GPIO_InitTypeDef *GPIO_InitStruct) 
  // Fills each GPIO_InitStruct member with its default value. 

void  GPIO_Write (GPIO_TypeDef *GPIOx, uint16_t PortVal) 
  // Writes data to the specified GPIO data port. 

void  GPIO_WriteBit (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, BitAction BitVal) 
  // Sets or clears the selected data port bit. 

对于本题目而言,使用简单的写入操作即可。

int main()
{
    led_gpio_config();
    GPIO_WriteBit(GPIOB, GPIO_Pin_5, 1);    //初始化,使灯为熄灭状态
    key_gpio_config();

    while(1) {
        if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1) {
            GPIO_WriteBit(GPIOB, GPIO_Pin_5, Bit_RESET);
        }
        else {
            GPIO_WriteBit(GPIOB, GPIO_Pin_5, Bit_SET);
        }
    }
}

至此,GPIO的操作完成,功能也成功实现。但是按键部分未加消抖处理,所以可能出现不稳定的状态。不过对于本示例来说,这一现象并不明显。

点这里可以跳转到人工智能网站

发表评论