簡介
不同的開發板的原理圖結構也不盡相同,筆者在這裏使用野火的MINI-V3(F103VET6)簡易開發板對GPIO口的設置做一個簡單的介紹,並實現按鍵控制LED燈的亮滅。方便讀者可以快速熟悉並靈活應用。
原理圖分析
首先我們來看一下發光二極管部分和按鍵部分的原理圖。
下面是按鍵的原理圖部分:
在這裏,我們將使用KEY1(PA0)來控制紅燈PB5的亮滅。由原理圖可知,其控制LED燈的PB5引腳爲低電平時,燈亮。當KEY1按下時,PA0引腳由之前的低電平轉爲高電平(3V3)。明確了目的之後我們就可以分析GPIO口並進行設置了。
GPIO設置
經過上述的功能明確之後,我們將其分爲兩大類,分別是輸入類(如按鍵)和輸出類(LED燈)。
STM32系列單片機的引腳有着豐富的功能,在這裏將其芯片的GPIO口部分的結構圖放出,有興趣的朋友可自行研究或在評論區留言討論。在這裏筆者將不再講解時鐘樹的相關內容,以免對初學者造成較大壓力,有興趣的朋友可自行參考官方文檔。
輸入輸出模式
GPIO的輸入、輸出種類詳見下表。
功能 | 名稱 | 簡述 |
---|---|---|
輸入 | 上拉輸入(GPIO_Mode_IPU) | 默認狀態下(引腳無輸入),讀得的數據爲1,高電平 |
輸入 | 下拉輸入(GPIO_Mode_IPD) | 與上拉輸入相反,默認爲0,低電平 |
輸入 | 浮空輸入(GPIO_Mode_IN_FLOATING) | 輸入不確定,無上拉和下拉。輸入阻抗較大,一般用於標準通信協議如 |
輸入 | 模擬輸入模式(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的操作完成,功能也成功實現。但是按鍵部分未加消抖處理,所以可能出現不穩定的狀態。不過對於本示例來說,這一現象並不明顯。