1. 程式人生 > 其它 >按鍵輸入實驗

按鍵輸入實驗

技術標籤:微控制器stm32

一、硬體設計

本實驗用到的硬體資源有: 1 ) 指示燈 DS0 DS1 2 3 個按鍵: KEY0 KEY1 KEY_UP DS0 DS1 STM32 的連線在上一章已經介紹了,在 MiniSTM32 開發板上的按鍵 KEY0連線在 PC5 上、 KEY1 連線在 PA15 上、 WK_UP 連線在 PA0 上。如圖 7.2.1 所示: 7.2.1 按鍵與 STM32 連線原理圖 這裡需要注意的是: KEY0 KEY1 是低電平有效的,而
WK_UP 是高電平有效的,除了KEY1 有上拉電阻(與 JTDI 共用),其他兩個都沒有上下拉電阻,所以,需要在 STM32 內部設 置上下拉。

二、軟體設計

1、先開啟 key.c 檔案,程式碼如下:

#include "key.h"
#include "delay.h"
//按鍵初始化函式
//PA15 和 PC5 設定成輸入
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ALIENTEK MiniSTM32 V3.0 開發板教程
140
STM32 不完全手冊(庫函式版)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,
ENABLE);//使能 PORTA,PORTC 時鐘
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
//關閉 jtag,使能 SWD,可以用 SWD 模式除錯
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PA15
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //設定成上拉輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化 GPIOA15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//PC5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //設定成上拉輸入
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化 GPIOC5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//PA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 設定成輸入,預設下拉 
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化 GPIOA.0
} 
//按鍵處理函式
//返回按鍵值
//mode:0,不支援連續按;1,支援連續按;
//返回值:
//0,沒有任何按鍵按下
//KEY0_PRES,KEY0 按下
//KEY1_PRES,KEY1 按下
//WKUP_PRES,WK_UP 按下
//注意此函式有響應優先順序,KEY0>KEY1>WK_UP!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;//按鍵按鬆開標誌
if(mode)key_up=1; //支援連按 
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
{
delay_ms(10);//去抖動
key_up=0;
if(KEY0==0)return KEY0_PRES;
else if(KEY1==0)return KEY1_PRES;
else if(WK_UP==1)return WKUP_PRES; 
}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1; 
return 0;// 無按鍵按下
}
這段程式碼包含 2 個函式, void KEY_Init(void) u8 KEY_Scan(u8 mode) KEY_Init 是用來初始化按鍵輸入的 IO 口的。實現 PA0 PA15 PC5 的輸入設定,注意這呼叫了: GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); 這個函式,用於禁止 JTAG 開啟 SWD ,因為 PA15 佔用了 JTAG 的一個 IO ,所以要禁止 JTAG ,從而讓 PA15 用作普通 IO 輸入。 KEY_Scan 函式,則是用來掃描這
3 IO 口是否有按鍵按下。 KEY_Scan 函式,支援兩種 掃描方式,通過 mode 引數來設定。 mode 0 的時候, KEY_Scan 函式將不支援連續按,掃描某個按鍵,該按鍵按下之後必須要鬆開,才能第二次觸發,否則不會再響應這個按鍵,這樣的好處就是可以防止按一次多次 觸發,而壞處就是在需要長按的時候就不合適了。 mode 1 的時候, KEY_Scan 函式將支援連續按,如果某個按鍵一直按下,則會一直返回這個按鍵的鍵值,這樣可以方便的實現長按檢測。 有了 mode 這個引數,大家就可以根據自己的需要,選擇不同的方式。 這裡要提醒大家, 因為該函式裡面有 static 變數,所以該函式不是一個可重入函式,在有 OS 的情況下,這個大家 要留意下。同時還有一點要注意的就是,該函式的按鍵掃描是有優先順序的,最優先的是 KEY0 第二優先的是 KEY1 ,最後是 WK_UP 按鍵。該函式有返回值,如果有按鍵按下,則返回非 0 值,如果沒有或者按鍵不正確,則返回 0

2、接下來我們看看標頭檔案 key.h 裡面的程式碼

#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
#define KEY0 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)//讀取按鍵 0
#define KEY1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)//讀取按鍵 1
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//讀取按鍵 2 
#define KEY0_PRES 1 //KEY0 
#define KEY1_PRES 2 //KEY1 
#define WKUP_PRES 3 //WK_UP 
void KEY_Init(void);//IO 初始化
u8 KEY_Scan(u8 mode); //按鍵掃描函式
#endif 這段程式碼裡面最關鍵就是 3 個巨集定義:
#define KEY0 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)//讀取按鍵 0
#define KEY1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)//讀取按鍵 1
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//讀取按鍵 2
前面跑馬燈實驗用的是位帶操作實現設定某個 IO 口的位。這裡我們採取的是庫函式的讀取 IO 口的值。當然,上面的功能也同樣可以通過位帶操作來簡單的實現:
//#define KEY0 PCin(5) 
//#define KEY1 PAin(15)
//#define WK_UP PAin(0)

3、最後,我們看看 main.c 裡面編寫的主函式程式碼如下:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "key.h"
//ALIENTEK Mini STM32 開發板範例程式碼 2
//按鍵輸入實驗 
//技術支援:www.openedv.com
//廣州市星翼電子科技有限公司
int main(void)
{
u8 t; 
delay_init(); //延時函式初始化 
LED_Init(); //初始化與 LED 連線的硬體介面
KEY_Init(); //初始化與按鍵連線的硬體介面
LED0=0; //點亮 LED
while(1)
{
t=KEY_Scan(0); //得到鍵值
switch(t)
{
case KEY0_PRES:
LED0=!LED0;
break;
case KEY1_PRES:
LED1=!LED1;
break;
case WKUP_PRES:
LED0=!LED0;
LED1=!LED1;
break;
default:
delay_ms(10);
} 
} }

編譯結果: