標籤:

GPIO輸入——按鍵檢測

當按下一個按鍵時,系統是如何檢測到的呢?

我們通過LED燈的亮滅狀態來間接完成按鍵檢測。當按下按鍵時,LED燈亮,再次按下時,LED燈滅。

要完成這個實驗,我們就會用到GPIO外設的基本輸入功能

查閱開發板的按鍵原理圖,如圖3-1。

圖3-1

圖中的K1、K2即為按鍵。以K1為例,當未按下按鍵時,其PA0引腳處於接地狀態,即低電平,按下按鍵時,引腳接到電源,輸入狀態為高電平。所以只要我們檢測按鍵對應引腳(這裡是PA0)的輸入電平狀態,即可判斷按鍵是否被按下。這便是按鍵的檢測原理了。

有一點需要知道,由於機械按鍵的彈性作用,按下按鍵時並不會馬上穩定接通或斷開,即存在按鍵抖動。一般情況下我們需要通過軟體或硬體的方式消抖才能得到理想的實驗效果。軟體消抖如通過定時器延時等方式,忽略前後的抖動;而硬體消抖,如可以利用電容的充放電延時等方式。本文默認已經進行過消抖處理了。

直接開始編程環節的分析。

首先得使能GPIO埠的時鐘,然後初始化按鍵和LED燈的引腳,最後通過讀取引腳不同電平狀態控制LED燈的狀態切換。這便是這個實驗的大致步驟了。

使能GPIO埠時鐘

所有的GPIO外設都掛載在APB2匯流排上,所以其使能寄存器為RCC_APB2ENR,查閱固件庫手冊可得其固件函數為RCC_APB2PeriphClockCmd(該固件函數功能即為對RCC_APB2ENR寄存器操作的封裝)。我們需要使能的是GPIOA時鐘,所以可調用如下API實現使能時鐘:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);n

初始化按鍵和LED燈

在使能GPIOA時鐘後,便開始初始化按鍵和LED燈了。我們需要用到GPIO_Init固件函數(該函數實現對配置引腳模式的封裝),將引腳配置為浮空輸入模式。這一步我們可以寫一個函數將其封裝起來。如下代碼:

/**n * @brief 初始化按鍵n * @param 無n * @retval 無n */nvoid Key_GPIO_Config(void){nn GPIO_InitTypeDef GPIO_InitStructure;n RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);n GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 選擇按鍵引腳PA0 n GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 設置引腳模式為浮空輸入n GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化按鍵nn}n

註:IO口為輸入模式時,不用設置輸出速率。

同樣的,由於我們需要通過LED燈來間接完成按鍵檢測(這裡我們使用的是RGB燈,使用G色的引腳PB0),所以以上步驟也需要對LED燈的PB0引腳重複一遍,其流程與按鍵初始化流程類似,這裡就不再贅述了,讀者可參考按鍵流程完成。

檢測按鍵狀態

接下來就需要通過檢測按鍵引腳的電平狀態來判斷按鍵是否按下了。那麼我們怎麼獲取引腳的電平狀態呢,查閱參考手冊可知,我們可以通過讀取IDR寄存器的值來獲取。而這個操作同樣被STM32固件庫封裝了,其函數名為GPIO_ReadInputDataBit。查看源碼,其正是對IDR寄存器操作的封裝,如下圖3-2所示。

圖3-2n

其最終會返回引腳的電平狀態,即返回1(高電平),返回0(低電平)。代碼里「Bit_RESET」和「Bit_SET」已經通過枚舉方式定義了,Bit_RESET=0(低電平),Bit_SET=1(高電平)。最後我們通過判斷函數返回值完成按鍵檢測。若按鍵按下,則引腳輸出高電平。我們將該檢測過程也封裝為一個函數Key_DETECTOR,具體如下:

/**n * @brief 檢測按鍵狀態n * @param GPIOx:x可以是A, B, C, D, En * GPIO_Pin:對應引腳序號n * @retval 1(高電平,即按下按鍵)、0(低電平,即沒有按下按鍵)n */nuint8_t Key_DETECTOR(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin){n n uint16_t keyState = GPIO_ReadInputDataBit(GPIOx, GPIO_Pin);n tttn /* 檢測是否按下按鍵 */n if(keyState){ntreturn 1;t n }else{n return 0;n }nttn}n

萬事俱備,只欠東風,我們終於可以開始寫main函數了。main函數里,需要逐步調用以上所述的API,完成實驗功能。直接上代碼:

// 定義控制LED的引腳n#define LED_TOGGLEtt LED_Control(GPIOB, GPIO_Pin_0)n// 使用帶參宏輸出LED燈的另一種狀態n#define LED_Control(GPIOx, GPIO_Pin) {GPIOx->ODR ^= GPIO_Pin;}nnint main(void){nn uint8_t SaveStatus = 0;n uint8_t State;nn LED_GPIO_Config();n Key_GPIO_Config();tnn while(1) n {tn State = Key_DETECTOR(GPIOA, GPIO_Pin_0);ntif(SaveStatus != State)nt{nt if(State == 1)nt {nt LED_TOGGLE;tttttnt }nt SaveStatus = State;ttttnt}n }nn}n

至此,我們的按鍵檢測實驗也分析完成了。把實驗效果上傳到優酷了,小夥伴們可以到優酷看最終效果,視頻只有幾秒鐘,可以放心打開喔。

註:本文封面照片也是實拍的實驗效果

GPIO輸入——按鍵檢測實驗結果記錄—在線播放—優酷網,視頻高清在線觀看 http://v.youku.com/v_show/id_XMTgxOTI5Mzc4MA==.html

--------------------------------------------------------------------

文章首發於知乎,轉載請私信,並註明原文出處。


推薦閱讀:

Alere Triage晶元的內部結構和檢測機理
人臉檢測與識別的趨勢和分析
金屬材料檢測專業該如何建立知識體系?

TAG:检测 |