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) 輸入不確定,無上拉和下拉。輸入阻抗較大,一般用於標準通信協議如I2C 、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的操作完成,功能也成功實現。但是按鍵部分未加消抖處理,所以可能出現不穩定的狀態。不過對於本示例來說,這一現象並不明顯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章