菜鳥學STM32之按鍵輸入


微信公眾號:小樊Study
關注共同學習,問題或建議,請公眾號留言!!!

跑馬燈實驗我們學習了STM32F4的IO口作為輸出的使用,這次我們將向大家介紹如何使用 STM32F4的IO口作為輸入用,今天我們將利用開發板的4個按鍵,來控制開發板的兩個LED的亮滅和蜂鳴器的開關。通過本次學習,你將了解到STM32F4的IO口作為輸入口的使用方法。

硬件連接


KEY0、KEY1 和 KEY2 是低電平有效的,而 KEY_UP 是高電平有效的,並且外部都沒有上下拉電阻,所以,需要在STM32F4內部設置上下拉

 

軟件設計

key.c

 1#include "key.h"
2#include "delay.h" 
3//////////////////////////////////////////////////////////////////////////////////     
4
5
6//按鍵初始化函數
7void KEY_Init(void)
8
{
9
10    GPIO_InitTypeDef  GPIO_InitStructure;
11
12  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA,GPIOE時鍾
13
14  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //KEY0 KEY1 KEY2對應引腳
15  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通輸入模式
16  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
17  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
18  GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4
19
20
21  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//WK_UP對應引腳PA0
22  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;//下拉
23  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA0
24
25
26//按鍵處理函數
27//返回按鍵值
28//mode:0,不支持連續按;1,支持連續按;
29//0,沒有任何按鍵按下
30//1,KEY0按下
31//2,KEY1按下
32//3,KEY2按下 
33//4,WKUP按下 WK_UP
34//注意此函數有響應優先級,KEY0>KEY1>KEY2>WK_UP!!
35u8 KEY_Scan(u8 mode)
36
{     
37    static u8 key_up=1;//按鍵按松開標志
38    if(mode)key_up=1;  //支持連按         
39    if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
40    {
41        delay_ms(10);//去抖動 
42        key_up=0;
43        if(KEY0==0)return 1;
44        else if(KEY1==0)return 2;
45        else if(KEY2==0)return 3;
46        else if(WK_UP==1)return 4;
47    }else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;      
48     return 0;// 無按鍵按下
49}


這段代碼包含 2 個函數,void KEY_Init(void)和 u8 KEY_Scan(u8 mode),KEY_Init 是用來初始化按鍵輸入的 IO 口的。實現 PA0、PE2~4 的輸入設置
KEY_Scan 函數,則是用來掃描這 4 個 IO 口是否有按鍵按下。KEY_Scan 函數,支持兩種掃描方式,通過 mode 參數來設置。
當 mode 為 0 的時候,KEY_Scan 函數將不支持連續按,掃描某個按鍵,該按鍵按下之后必須要松開,才能第二次觸發,否則不會再響應這個按鍵,這樣的好處就是可以防止按一次多次觸發,而壞處就是在需要長按的時候比較不合適。
當 mode 為 1 的時候,KEY_Scan 函數將支持連續按,如果某個按鍵一直按下,則會一直返回這個按鍵的鍵值,這樣可以方便的實現長按檢測。
有了 mode 這個參數,大家就可以根據自己的需要,選擇不同的方式。這里要提醒大家,因為該函數里面有 static 變量,所以該函數不是一個可重入函數,在有 OS 的情況下,這個大家要留意下。同時還有一點要注意的就是,該函數的按鍵掃描是有優先級的,最優先的是 KEY0,第二優先的是 KEY1,接着 KEY2,最后是 KEY3(KEY3 對應 KEY_UP 按鍵)。該函數有返回值,如果有按鍵按下,則返回非 0 值,如果沒有或者按鍵不正確,則返回 0。

key.h

 1#ifndef __KEY_H
2#define __KEY_H     
3#include "sys.h" 
4
5/*下面方式是通過位帶操作方式讀取IO*/
6
7#define KEY0         PEin(4)     //PE4
8#define KEY1         PEin(3)     //PE3 
9#define KEY2         PEin(2)     //P32
10#define WK_UP     PAin(0)     //PA0
11
12
13
14#define KEY0_PRES     1
15#define KEY1_PRES    2
16#define KEY2_PRES    3
17#define WKUP_PRES   4
18
19void KEY_Init(void);    //IO初始化
20u8 KEY_Scan(u8);          //按鍵掃描函數    
21
22#endif


main.c

 1#include "sys.h"
2#include "delay.h"
3#include "usart.h"
4#include "led.h"
5#include "beep.h"
6#include "key.h"
7
8
9
10
11int main(void)
12

13
14  u8 key;           //保存鍵值
15    delay_init(168);  //初始化延時函數
16    LED_Init();             //初始化LED端口 
17    BEEP_Init();      //初始化蜂鳴器端口
18    KEY_Init();       //初始化與按鍵連接的硬件接口
19    LED0=0;                 //先點亮紅燈
20    while(1)
21    {
22        key=KEY_Scan(0);        //得到鍵值
23        if(key)
24        {                          
25            switch(key)
26            {                
27                case WKUP_PRES: //控制蜂鳴器
28                    BEEP=!BEEP;
29                    break;
30                case KEY0_PRES: //控制LED0翻轉
31                    LED0=!LED0;
32                    break;
33                case KEY1_PRES: //控制LED1翻轉   
34                    LED1=!LED1;
35                    break;
36                case KEY2_PRES: //同時控制LED0,LED1翻轉 
37                    LED0=!LED0;
38                    LED1=!LED1;
39                    break;
40            }
41        }else delay_ms(10); 
42    }
43
44}

主函數代碼比較簡單,先進行一系列的初始化操作,然后在死循環中調用按鍵掃描函數KEY_Scan()掃描按鍵值,最后根據按鍵值控制 LED 和蜂鳴器的翻轉。

下載驗證

在下載完之后,我們可以按 KEY0、KEY1、KEY2和 KEY_UP 來看看 DS0 和 DS1 以及蜂鳴器的變化,是否和我們預期的結果一致?

 

下面的是我的公眾號二維碼圖片,歡迎關注。

圖注:小樊Study圖注:小樊Study


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM