前言
做完了GPIO點(diǎn)燈實(shí)驗(yàn),成就感滿滿,不知道小白的我是不是入門了,哈哈!開始做下一個(gè)GPIO按鍵檢測(cè)的實(shí)驗(yàn)。
一、硬件電路設(shè)計(jì)
1.開發(fā)板用戶按鍵硬件電路
輕觸按鍵又稱輕觸開關(guān)(下文簡稱按鍵),是電路中常用的一種開關(guān)元器件,也是一種常用的人機(jī)接口。廣泛用于家電、數(shù)碼產(chǎn)品、便攜儀產(chǎn)品、電腦產(chǎn)品等電子設(shè)備中。
STC8A8K64S4A12開發(fā)板上設(shè)計(jì)了4個(gè)用戶按鍵KEY1、KEY2、KEY3、KEY4,當(dāng)使用KEY1和KEY2時(shí),可短接J26端子的P37||KEY1、P36||KEY2。程序中通過讀取這些按鍵對(duì)應(yīng)的GPIO的狀態(tài)(高電平或低電平)可判斷該按鍵是否按下,這種電路的形式稱為高低電平接法,這種檢測(cè)按鍵的方法稱為按鍵高低電平檢測(cè)。
圖1:開發(fā)板按鍵檢測(cè)電路及實(shí)物圖
表1:用戶按鍵引腳分配
輕觸按鍵,顧名思義我們只需要施加很小的力量即可改變開關(guān)連接的狀態(tài)。輕觸按鍵在所需外力作用下(按下按鍵)觸點(diǎn)導(dǎo)通,無外力作用時(shí)(釋放按鍵)觸點(diǎn)斷開,如下圖所示:
圖2:輕觸按鍵原理
2.按鍵檢測(cè)接法
高低電平式接法是最常見的按鍵檢測(cè)的接法,顧名思義,該接法就是需要單片機(jī)引腳具有高低電平的檢測(cè)能力,也就是常見的GPIO引腳即可。高低電平式接法又可分為兩種:獨(dú)立式接法和行列式接法。
行列式接法是利用單片機(jī)的 GPIO口組成行與列,在行與列的每一個(gè)交點(diǎn)處連接按鍵。 故也稱為矩陣式按鍵,該接線方法最大的優(yōu)勢(shì)是可以使用較少的GPIO口實(shí)現(xiàn)較多按鍵的檢測(cè),這個(gè)在矩陣按鍵掃描實(shí)驗(yàn)中會(huì)詳細(xì)介紹。
獨(dú)立式接法的含義就是使用單片機(jī)的一個(gè)GPIO引腳檢測(cè)一個(gè)按鍵的狀態(tài),有多少按鍵需檢測(cè)就需要多少個(gè)GPIO引腳,對(duì)每個(gè)按鍵的檢測(cè)相互獨(dú)立。
獨(dú)立式按鍵接法一般會(huì)用低電平有效的方式,即按鍵按下是GPIO輸入為低電平,如下圖所示。
圖3:獨(dú)立式接法
上圖中的電阻R的作用是將GPIO輸入端口不確定的信號(hào)通過該電阻鉗位在高電平狀態(tài)。我們知道數(shù)字電路有三種狀態(tài):高電平、低電平和高阻狀態(tài),有些應(yīng)用場(chǎng)合并不希望出現(xiàn)高阻狀態(tài),這時(shí)加上拉電阻即可讓GPIO輸入端口保持確定的狀態(tài)。
按鍵釋放時(shí),因?yàn)樯侠娮鑂的關(guān)系,GPIO輸入檢測(cè)是高電平,按鍵閉合時(shí),GPIO短接到GND,輸入檢測(cè)是低電平。這樣,單片機(jī)根據(jù)GPIO的輸入狀態(tài)即可確定按鍵是否按下。
■ 按鍵檢測(cè)知識(shí)擴(kuò)展:ADC通過電阻分壓檢測(cè)多個(gè)按鍵
按鍵檢測(cè)除了高低電平檢測(cè)的方法之外,還有一種方法是使用ADC通過電阻分壓檢測(cè)多個(gè)按鍵,這種按鍵檢測(cè)的電路形式稱為分壓式接法。
分壓式接法,使用的單片機(jī)引腳必須具有ADC功能,根據(jù)檢測(cè)口測(cè)得的不同的電壓值來識(shí)別是哪個(gè)按鍵被按下。如下圖所示,是分壓式接法的原理示意圖。這種方法最大的好處是節(jié)省IO資源,它只需一個(gè)具有ADC功能的IO即可實(shí)現(xiàn)多個(gè)按鍵的檢測(cè),它適用于IO資源緊張的場(chǎng)合,如一些電磁爐的按鍵使用的就是這種方法。
相對(duì)于高低電平檢測(cè),這種方法在編程上要復(fù)雜一些,需要事先計(jì)算好分壓的電壓值,存儲(chǔ)于“表”中,程序運(yùn)行時(shí),采樣到電壓值后查表即可獲知是哪個(gè)按鍵按下。
圖4:分壓式接法原理
3.按鍵檢測(cè)電路考慮因素
按鍵檢測(cè)電路設(shè)計(jì)的時(shí)候,需要我們考慮兩個(gè)方面:按鍵釋放時(shí)GPIO口狀態(tài)的確定和按鍵消抖。
1)按鍵釋放時(shí)GPIO口狀態(tài)的確定
按鍵檢測(cè)電路中,當(dāng)按鍵釋放后要能保證GPIO口電平是確定的,即按鍵釋放時(shí)GPIO口固定為高電平或低電平。開發(fā)板RN1排阻就是滿足用戶按鍵釋放時(shí),在單片機(jī)GPIO口上保持高電平。
2)按鍵消抖
對(duì)于按鍵硬件上的消抖,一般常用的方式是在按鍵上并接一個(gè)容值約0.1uF左右電容,利用電容兩端的電壓不能突變的特性,消除抖動(dòng)時(shí)產(chǎn)生的毛刺電壓。雖然電容可以起到消除抖動(dòng)的作用,但是在考慮按鍵靈敏度的情況下,電容時(shí)無法完全消除抖動(dòng)的,消除抖動(dòng)還需要軟件的配合。
開發(fā)板上按鍵電路沒有增加硬件消抖,開發(fā)板使用的是軟件消抖,這對(duì)于一般的按鍵檢測(cè)已經(jīng)完全足夠。
3)GPIO口保護(hù)
開發(fā)板按鍵檢測(cè)電路中還串有排阻RN12,該排阻阻值100歐姆,串在單片機(jī)GPIO口和按鍵引腳中,起到保護(hù)GPIO口的目的。
分析:如果GPIO口不小心誤配置為輸出模式,并且輸出高電平,則分析下電路可知,此時(shí)如果沒有排阻RN12,若按下用戶按鍵,則單片機(jī)GPIO口(控制輸出高電平)直接和GND相連,會(huì)損壞GPIO口。
二、軟件設(shè)計(jì)
1.寄存器解析
1.1.端口數(shù)據(jù)寄存器
下圖是對(duì)端口數(shù)據(jù)寄存器P0、P1、P2、P3、P4、P5、P6、P7的描述,端口數(shù)據(jù)寄存器各位代表對(duì)應(yīng)端口的GPIO口,在完成對(duì)配置寄存器設(shè)置后,可直接讀取端口引腳電平。
圖5:端口數(shù)據(jù)寄存器
1.2.端口上拉電阻控制寄存器
下圖是對(duì)端口上拉電阻控制寄存器P0PU、P1PU、P2PU、P3PU、P4PU、P5PU、P6PU、P7PU的描述,這些特殊功能寄存器不支持位尋址。端口上拉電阻控制寄存器各位代表對(duì)應(yīng)端口的GPIO口是否使能其上拉電阻,在完成對(duì)該寄存器設(shè)置后,相應(yīng)GPIO端口便在單片機(jī)內(nèi)部有了上拉電阻。該功能使得GPIO口在硬件電路設(shè)計(jì)時(shí)具有了更多的靈活性。但務(wù)必知曉端口上拉電阻控制寄存器為擴(kuò)展SFR,邏輯地址位于XDATA區(qū)域,訪問前需先將P_SW2寄存器的最高位(EAXFR)置1。
圖6:端口數(shù)據(jù)寄存器
2.GPIO輸入按鍵檢測(cè)實(shí)驗(yàn)(單個(gè)c文件)
2.1.頭文件引用和路徑設(shè)置
■ 需要宏定義部分及引用的頭文件
因?yàn)樵凇癿ain.c”文件中使用了STC8的頭文件“STC8.h”,所以需要引用下面的頭文件。在頭文件“STC8.h”中需要確定主時(shí)鐘取值,所以宏定義主時(shí)鐘值。
#define MAIN_Fosc 11059200L //定義主時(shí)鐘
#include "STC8.H"
在程序設(shè)計(jì)中會(huì)用到定義變量的類型,為了定義變量方便,將較為復(fù)雜的“unsigned int”和“unsigned char ”進(jìn)行了宏定義。
#define uint16 unsigned int
#define uint8 unsigned char
這樣,再定義變量時(shí)可直接使用“uint16”和“uint8”來取代“unsigned int”和“unsigned char ”即可。
■ 需要包含的頭文件路徑
本例需要包含的頭文件路徑如下表:
表2:頭文件包含路徑
MDK中點(diǎn)擊魔術(shù)棒,打開工程配置窗口,按照下圖所示添加頭文件包含路徑。
圖7:添加頭文件包含路徑
2.2.編寫代碼
首先根據(jù)開發(fā)板按鍵及指示燈GPIO分配,定義寄存器位變量,代碼如下。
/**********************
引腳別名定義
***********************/
sbit KEY=P0^7; //用戶按鍵KEY3用IO口P07
sbit LED_D3=P7^2; //用戶指示燈D3用IO口P72
然后,在主函數(shù)中先對(duì)P7.2和P0.7口進(jìn)行模式配置,后主循環(huán)中檢測(cè)按鍵狀態(tài),確認(rèn)按鍵按下控制藍(lán)色指示燈D3亮。
int main(void)
{
P7M1 &= 0xFB; P7M0 &= 0xFB; //設(shè)置P7.2為準(zhǔn)雙向口
P0M1 &= 0x7F; P0M0 &= 0x7F; //設(shè)置P0.7為準(zhǔn)雙向口
// P0M1 |= 0x80; P0M0 &= 0x7F; //設(shè)置P0.7為高阻輸入
while(1)
{
if(KEY == 0) //檢測(cè)用戶按鍵KEY3對(duì)應(yīng)引腳P0.7是否是低電平 (按鍵按下,引腳為低電平)
{
delay_ms(10); //軟件延時(shí)10ms,如果延時(shí)后按鍵KEY3的電平依然沒有變化,說明按鍵確實(shí)被有效操作,簡稱按鍵消抖
if(KEY== 0) //檢測(cè)用戶按鍵KEY3對(duì)應(yīng)引腳P0.7是否依然是低電平
{
LED_D3=0; //點(diǎn)亮用戶指示燈D3
while(KEY == 0) //等待按鍵KEY3釋放,即如果P0.7一直為低電平,會(huì)一直執(zhí)行空命令
{
; //條件KEY == 0成立,會(huì)執(zhí)行這個(gè)空命令
}
LED_D3=1; //按鍵KEY3釋放,熄滅用戶指示燈D3
}
}
}
}
3.流水燈實(shí)驗(yàn)(多個(gè)c文件)
3.1.工程需要用到的c文件
本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。
表3:實(shí)驗(yàn)需要用到的c文件
3.2.頭文件引用和路徑設(shè)置
■ 需要引用的頭文件
因?yàn)樵凇癿ain.c”文件中使用了控制led的函數(shù)和延時(shí)函數(shù)(延時(shí)函數(shù)沒有在main.c中定義),所以需要引用下面的頭文件。
#include "led.h"
#include "delay.h"
#include "key.h"
■ 需要包含的頭文件路徑
本例需要包含的頭文件路徑如下表:
表4:頭文件包含路徑
MDK中點(diǎn)擊魔術(shù)棒,打開工程配置窗口,按照下圖所示添加頭文件包含路徑。
圖8:添加頭文件包含路徑
3.3.編寫代碼
首先在key.h中,宏定義4個(gè)用戶按鍵,引用延時(shí)函數(shù)的頭文件,聲明按鍵檢測(cè)函數(shù)供外部調(diào)用。代碼如下。
#include "delay.h"
#define KEY_ON 0
#define KEY_OFF 1
#define KEYS_OFF 0 //沒有按鍵按下
#define KEY1_ON 1 //按鍵KEY1按下
#define KEY2_ON 2 //按鍵KEY2按下
#define KEY3_ON 3 //按鍵KEY3按下
#define KEY4_ON 4 //按鍵KEY4按下
/********************************************
引腳別名定義
*********************************************/
sbit KEY_S1=P3^7; //用戶按鍵KEY1用IO口P37
sbit KEY_S2=P3^6; //用戶按鍵KEY2用IO口P36
sbit KEY_S3=P0^7; //用戶按鍵KEY3用IO口P07
sbit KEY_S4=P0^5; //用戶按鍵KEY4用IO口P05
extern uint8 Keys_Scan(uint8 mode);
然后,在key.c文件中編寫一個(gè)按鍵檢測(cè)函數(shù)Keys_Scan,代碼如下。
程序清單:延時(shí)函數(shù)
/**************************************************************************
功能描述:檢測(cè)開發(fā)板上的4個(gè)用戶按鍵(KEY1、KEY2、KEY3、KEY4)
入口參數(shù):uint8 mode 是否支持連按
返回值:按鍵編號(hào)
*************************************************************************/
uint8 Keys_Scan(uint8 mode)
{
static uint8 Key_up=1; //標(biāo)志變量
if(mode==1) //支持連按
{
Key_up=1; //變量 Key_up會(huì)被重新賦值為1
}
//檢測(cè)按鍵KEY1、按鍵KEY2、按鍵KEY3、按鍵KEY4用IO口電平是否為低電平
if(Key_up&&((KEY_S1 == KEY_ON ) || (KEY_S2 == KEY_ON ) || (KEY_S3 == KEY_ON ) || (KEY_S4 == KEY_ON )))
{
delay_ms(10); //軟件延時(shí)10ms,去抖
Key_up=0; //變量 Key_up會(huì)被賦值為0
if(KEY_S1 == KEY_ON )
{
return KEY1_ON;
}
else if(KEY_S2 == KEY_ON )
{
return KEY2_ON;
}
else if(KEY_S3 == KEY_ON )
{
return KEY3_ON;
}
else if(KEY_S4 == KEY_ON )
{
return KEY4_ON;
}
}
else if((KEY_S1 == KEY_OFF )&&(KEY_S2 == KEY_OFF ) &&(KEY_S3 == KEY_OFF )&&(KEY_S4 == KEY_OFF ) )
{
Key_up=1; //變量 Key_up會(huì)被賦值為1
}
return KEYS_OFF;
}
因?yàn)榘存I檢測(cè)函數(shù)Keys_Scan中使用了控制led的函數(shù)、有關(guān)KEY的宏定義和延時(shí)函數(shù),所以需要在key.c文件中引用下面的頭文件。
#include "led.h"
#include "key.h"
最后,在主函數(shù)中先對(duì)4個(gè)用戶指示燈和4個(gè)用戶按鍵用到的GPIO口進(jìn)行模式配置,后主循環(huán)中調(diào)用按鍵檢測(cè)函數(shù),可觀察各用戶按鍵按下后用戶指示燈變化情況。
代碼清單:主函數(shù)
int main(void)
{
uint8 temp;
P2M1 &= 0x3F; P2M0 &= 0x3F; //設(shè)置P2.6~P2.7為準(zhǔn)雙向口
P7M1 &= 0xF9; P7M0 &= 0xF9; //設(shè)置P7.1~P7.2為準(zhǔn)雙向口
P0M1 &= 0x5F; P0M0 &= 0x5F; //設(shè)置P0.5,P0.7為準(zhǔn)雙向口
// P0M1 |= 0xA0; P0M0 &= 0x5F; //設(shè)置P0.5,P0.7為高阻輸入
P3M1 &= 0x3F; P3M0 &= 0x3F; //設(shè)置P3.6~P3.7為準(zhǔn)雙向口
// P3M1 |= 0xC0; P3M0 &= 0x3F; //設(shè)置P3.6~P3.7為高阻輸入
// P_SW2 |= 0x80; //將EAXFR位置1,以訪問在XDATA區(qū)域的擴(kuò)展SFR
// P0PU |= 0xA0; //設(shè)置P0.5,P0.7口有上拉電阻
// P3PU |= 0xC0; //設(shè)置P3.6~P3.7口有上拉電阻
// P_SW2 &= 0x7F; //將EAXFR位置0,恢復(fù)訪問XRAM
while(1)
{
temp=Keys_Scan(0); //獲取開發(fā)板用戶按鍵檢測(cè)值,不支持連按
if(temp == KEY1_ON) //如果按鍵KEY1被操作
{
led_toggle(LED_1); //控制用戶指示燈D1翻轉(zhuǎn)
}
else if(temp == KEY2_ON) //如果按鍵KEY2被操作
{
led_toggle(LED_2); //控制用戶指示燈D2翻轉(zhuǎn)
}
else if(temp == KEY3_ON) //如果按鍵KEY3被操作
{
led_toggle(LED_3); //控制用戶指示燈D3翻轉(zhuǎn)
}
else if(temp == KEY4_ON) //如果按鍵KEY4被操作
{
led_toggle(LED_4); //控制用戶指示燈D4翻轉(zhuǎn)
}
}
}
總結(jié)
以上就是今天要講的內(nèi)容,希望對(duì)你有所幫助!
-
元器件
+關(guān)注
關(guān)注
113文章
4835瀏覽量
95184 -
寄存器
+關(guān)注
關(guān)注
31文章
5434瀏覽量
124559 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5682瀏覽量
104854 -
GPIO
+關(guān)注
關(guān)注
16文章
1280瀏覽量
54122 -
按鍵檢測(cè)
+關(guān)注
關(guān)注
0文章
25瀏覽量
4938
發(fā)布評(píng)論請(qǐng)先 登錄
基于STC8A8K64S4A12開發(fā)板的GPIO點(diǎn)燈實(shí)驗(yàn)

STC8A8K64S4A12系列單片機(jī)DAC數(shù)模轉(zhuǎn)換器講解

請(qǐng)問哪位朋友有火龍電子FD51D_8(STC8A8K64S4A12開發(fā)板)的資料呢?
STC8A8K64S4A12開發(fā)板學(xué)習(xí)資料
淺析STC8A8K64S4A12開發(fā)板
如何去實(shí)現(xiàn)一種基于STC8A8K64S4A12開發(fā)板的GPIO按鍵設(shè)計(jì)
基于STC8A8K64S4A12智能車設(shè)計(jì)資料分享
STC8A8K64S4A12的命名規(guī)則是什么
STC8A8K64S4A12迷你開發(fā)板電路原理圖免費(fèi)下載

使用STC8A8K64S4A12單片機(jī)掉電喚醒定時(shí)器應(yīng)用的實(shí)例

【STC8A8K64S4A12開發(fā)板】—聊聊單片機(jī)中斷原理

基于STC8A8K64S4A12單片機(jī)硬件IIC_光照強(qiáng)度檢測(cè)

【STC8A8K64S4A12開發(fā)板】—4x4矩陣按鍵檢測(cè)

STC8A8K64S4A12的命名規(guī)則

評(píng)論