【STM32F429單片機(jī)學(xué)習(xí)】單片機(jī)學(xué)習(xí)之按鍵實(shí)驗(yàn)
按鍵實(shí)驗(yàn)文件組成
一、key.c(GPIO口的初始化、KEY的基本功能)
分析代碼(顏色一樣的為一步)
引入KEY、delay頭文件(有聲明與函數(shù))
#include "key.h"
#include "delay.h"
定義按鍵初始化函數(shù)(其實(shí)就是初始化IO口同LED的方法)
void KEY_Init(void)
{
定義GPIO的結(jié)構(gòu)體,因?yàn)镠AL_GPIO_Init的入口參數(shù)為兩個(gè)均為指針,其中之一為某個(gè)GPIO,另一個(gè)為結(jié)構(gòu)體,結(jié)構(gòu)體包含著pin的模式
??? GPIO_InitTypeDef GPIO_Initure;
??? 使用某個(gè)外設(shè)一定要打開其時(shí)鐘
??? __HAL_RCC_GPIOA_CLK_ENABLE();?????????? //開啟GPIOA時(shí)鐘
??? __HAL_RCC_GPIOC_CLK_ENABLE();?????????? //開啟GPIOC時(shí)鐘
??? __HAL_RCC_GPIOH_CLK_ENABLE();?????????? //開啟GPIOH時(shí)鐘
?? ?
設(shè)定IO 的輸出模式等,因?yàn)檫@是按鍵實(shí)驗(yàn)所以要MODE為輸入,KEY有時(shí)候低電平有效,有的時(shí)候高電平有效,這要看原理圖來確定其工作方式,查閱原理圖后,我將IO設(shè)置如下
??? GPIO_Initure.Pin=GPIO_PIN_0;??????????? //PA0
??? GPIO_Initure.Mode=GPIO_MODE_INPUT;????? //輸入
??? GPIO_Initure.Pull=GPIO_PULLDOWN;??????? //下拉
??? GPIO_Initure.Speed=GPIO_SPEED_HIGH;???? //高速
??? HAL_GPIO_Init(GPIOA,&GPIO_Initure);
?? ?
??? GPIO_Initure.Pin=GPIO_PIN_13;?????????? //PC13
??? GPIO_Initure.Mode=GPIO_MODE_INPUT;????? //輸入
??? GPIO_Initure.Pull=GPIO_PULLUP;????????? //上拉
??? GPIO_Initure.Speed=GPIO_SPEED_HIGH;???? //高速
??? HAL_GPIO_Init(GPIOC,&GPIO_Initure);
?? ?
??? GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3
??? HAL_GPIO_Init(GPIOH,&GPIO_Initure);
}
在我們初始化IO口,接下來就要設(shè)定他的具體功能了,初始化IO我認(rèn)為好比給汽車點(diǎn)火,而定義功能函數(shù)(如下的scan函數(shù))就好比開車出發(fā),首先我們要想到某個(gè)KEY按下后,單片機(jī)怎么檢測(cè)到是哪個(gè)KEY,仔細(xì)想想應(yīng)該是通過掃描(scan)某個(gè)IO口的高低電平來實(shí)現(xiàn),好比當(dāng)KEY1按下后對(duì)應(yīng)得IO有電平的變化,讓單片機(jī)知道是那個(gè)KEY 按下了
u8 KEY_Scan(u8 mode)
{
設(shè)置靜態(tài)參數(shù)(無(wú)符號(hào)8位整數(shù)u8,其范圍0-255,所以不用u16 u32),且返回值也為u8,key_up=1,他的值在循環(huán)進(jìn)入程序中不會(huì)改變,static(靜態(tài)),我們把這個(gè)key_up=1定義為一個(gè)標(biāo)識(shí)符,用來 標(biāo)定按鍵未能按下
??? static u8 key_up=1;???? //按鍵松開標(biāo)志
有兩種模式mode=0 or 1 選擇即可,我們這次mode=0
??? if(mode==1)key_up=1;??? //支持連按
這里的KEY0==1等,為宏定義其實(shí)背后就是一個(gè)HAL的READ函數(shù)可以讀取IO口的高低電平(0 OR 1),這里在.h文件中定義,此代碼為某個(gè)按鍵按下后也就是生效后,與我們的按鍵表示符 key_up=1 與一下,成立就表示按下 key_up=0,若無(wú)則 ? return 0
??? if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
??? {
??????? delay_ms(10);
??????? key_up=0;
如果有按鍵按下那么判斷一下到底哪個(gè)IO是什么樣的電平,來返回一個(gè)事件符就是 return KEY0_PRES,首先KEY0_PRES在.h中定義為宏常量目的是建立起4個(gè)事件(哪個(gè)按鈕被按下了),然后在mian.c中與swtich case 結(jié)合起來,執(zhí)行對(duì)應(yīng)的事件。
??????? if(KEY0==0)?????? return KEY0_PRES;
??????? else if(KEY1==0)? return KEY1_PRES;
??????? else if(KEY2==0)? return KEY2_PRES;
??????? else if(WK_UP==1) return WKUP_PRES;???????? ?
??? }else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;
??? return 0;?? //無(wú)按鍵按下
}
二、led.c(GPIO口的初始化、LED燈的基本功能)
請(qǐng)看LED跑馬燈實(shí)驗(yàn)講解
三、key.h
保護(hù)頭文件
#ifndef _KEY_H
#define _KEY_H
#include "sys.h"
定義宏變量也就是 HAL_GPIO_ReadPin讀取的參數(shù)傳遞給KEY0 ,看到這是不是對(duì)KEY.C文件中的操作就明白了
#define KEY0??????? HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_3)? //KEY0按鍵PH3
#define KEY1??????? HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_2)? //KEY1按鍵PH2
#define KEY2??????? HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) //KEY2按鍵PC13
#define WK_UP?????? HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)? //WKUP按鍵PA0
定義宏常亮,就是為了分成四個(gè)實(shí)驗(yàn) 到時(shí)候與swtich case 聯(lián)動(dòng)
#define KEY0_PRES ?? ?1
#define KEY1_PRES?? ??? ?2
#define KEY2_PRES?? ??? ?3
#define WKUP_PRES?? 4
聲明你在.c文件中的函數(shù)
void KEY_Init(void);
u8 KEY_Scan(u8 mode);
#endif
四、led.h
請(qǐng)看LED跑馬燈實(shí)驗(yàn)講解
五、main.c(GPIO口的初始化、LED燈的基本功能)
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
定義主函數(shù)
int main(void)
{
調(diào)用函數(shù)
??? u8 key;
??? HAL_Init();???????????????????? //初始化HAL庫(kù)? ?
??? Stm32_Clock_Init(360,25,2,8);?? //設(shè)置時(shí)鐘,180Mhz
??? delay_init(180);??????????????? //初始化延時(shí)函數(shù)
??? LED_Init();???????????????????? //初始化LED
??? KEY_Init();???????????????????? //初始化按鍵
?? ?構(gòu)造一個(gè)死循環(huán)
??? while(1)
??? {
key是一個(gè)返回值 switch通過判斷KEY的值來選擇事件
??????? key=KEY_Scan(0);??????????? //按鍵掃描
?? ??? ??? ??? ?switch(key)
?? ??? ??? ??? ?{?? ??? ??? ??? ?
?? ??? ??? ??? ??? ?case? WKUP_PRES:?? ?//控制LED0,LED1互斥點(diǎn)亮
?? ??? ??? ??? ??? ??? ??? ??? ?LED1=!LED1;
?? ??? ??? ??? ??? ??? ??? ??? ?LED0=!LED1;
?? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ?case? KEY2_PRES:?? ?//控制LED0翻轉(zhuǎn)
?? ??? ??? ??? ??? ??? ??? ??? ?LED0=!LED0;
?? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ?case? KEY1_PRES:?? ?//控制LED1翻轉(zhuǎn)?? ?
?? ??? ??? ??? ??? ??? ??? ??? ?LED1=!LED1;
?? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ?case? KEY0_PRES:?? ?//同時(shí)控制LED0,LED1翻轉(zhuǎn)
?? ??? ??? ??? ??? ??? ??? ??? ?LED0=!LED0;
?? ??? ??? ??? ??? ??? ??? ??? ?LED1=!LED1;
?? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ?}
??????? delay_ms(10);
??? }
}