新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > C51按鍵程序編寫的基礎(chǔ)

C51按鍵程序編寫的基礎(chǔ)

作者: 時(shí)間:2016-11-25 來(lái)源:網(wǎng)絡(luò) 收藏
從這一章開始,我們步入按鍵程序設(shè)計(jì)的殿堂。在基于單片機(jī)為核心構(gòu)成的應(yīng)用系統(tǒng)中,用戶輸入是必不可少的一部分。輸入可以分很多種情況,譬如有的系統(tǒng)支持PS2鍵盤的接口,有的系統(tǒng)輸入是基于編碼器,有的系統(tǒng)輸入是基于串口或者USB或者其它輸入通道等等。在各種輸入途徑中,更常見的是,基于單個(gè)按鍵或者由單個(gè)鍵盤按照一定排列構(gòu)成的矩陣鍵盤(行列鍵盤)。我們這一篇章主要討論的對(duì)象就是基于單個(gè)按鍵的程序設(shè)計(jì),以及矩陣鍵盤的程序編寫。

◎按鍵檢測(cè)的原理
常見的獨(dú)立按鍵,相信大家并不陌生,各種常見的開發(fā)板學(xué)習(xí)板上隨處可以看到他們的身影。

本文引用地址:http://m.butianyuan.cn/article/201611/321164.htm

總共有四個(gè)引腳,一般情況下,處于同一邊的兩個(gè)引腳內(nèi)部是連接在一起的,如何分辨兩個(gè)引腳是否處在同一邊呢?可以將按鍵翻轉(zhuǎn)過(guò)來(lái),處于同一邊的兩個(gè)引腳,有一條突起的線將他們連接一起,以標(biāo)示它們倆是相連的。如果無(wú)法觀察得到,用數(shù)字萬(wàn)用表的二極管擋位檢測(cè)一下即可。搞清楚這點(diǎn)非常重要,對(duì)于我們畫PCB的時(shí)候的封裝很有益。
它們和我們的單片機(jī)系統(tǒng)的I/O口連接一般如下:


對(duì)于單片機(jī)I/O內(nèi)部有上拉電阻微控制器而言,還可以省掉外部的那個(gè)上拉電阻。簡(jiǎn)單分析一下按鍵檢測(cè)的原理。當(dāng)按鍵沒有按下的時(shí)候,單片機(jī)I/O通過(guò)上拉電阻R接到VCC,我們?cè)诔绦蛑凶x取該I/O的電平的時(shí)候,其值為1(高電平); 當(dāng)按鍵S按下的時(shí)候,該I/O被短接到GND,在程序中讀取該I/O的電平的時(shí)候,其值為0(低電平) 。這樣,按鍵的按下與否,就和與該按鍵相連的I/O的電平的變化相對(duì)應(yīng)起來(lái)。結(jié)論:我們?cè)诔绦蛑型ㄟ^(guò)檢測(cè)到該I/O口電平的變化與否,即可以知道按鍵是否被按下,從而做出相應(yīng)的響應(yīng)。一切看起來(lái)很美好,是這樣的嗎?

◎現(xiàn)實(shí)并非理想
在我們通過(guò)上面的按鍵檢測(cè)原理得出上述的結(jié)論的時(shí)候,其實(shí)忽略了一個(gè)重要的問(wèn)題,那就是現(xiàn)實(shí)中按鍵按下時(shí)候的電平變化狀態(tài)。我們的結(jié)論是基于理想的情況得出來(lái)的,就如同下面這幅按鍵按下時(shí)候?qū)?yīng)電平變化的波形圖一樣:

而實(shí)際中,由于按鍵的彈片接觸的時(shí)候,并不是一接觸就緊緊的閉合,它還存在一定的抖動(dòng),盡管這個(gè)時(shí)間非常的短暫,但是對(duì)于我們執(zhí)行時(shí)間以u(píng)s為計(jì)算單位的微控制器來(lái)說(shuō),
它太漫長(zhǎng)了。因而,實(shí)際的波形圖應(yīng)該如下面這幅示意圖一樣。
這樣便存在這樣一個(gè)問(wèn)題。假設(shè)我們的系統(tǒng)有這樣功能需求:在檢測(cè)到按鍵按下的時(shí)候,將某個(gè)I/O的狀態(tài)取反。由于這種抖動(dòng)的存在,使得我們的微控制器誤以為是多次按鍵的按下,從而將某個(gè)I/O的狀態(tài)不斷取反,這并不是我們想要的效果,假如該I/O控制著系統(tǒng)中某個(gè)重要的執(zhí)行的部件,那結(jié)果更不是我們所期待的。于是乎有人便提出了軟件消除抖動(dòng)的思想,道理很簡(jiǎn)單:抖動(dòng)的時(shí)間長(zhǎng)度是一定的,只要我們避開這段抖動(dòng)時(shí)期,檢測(cè)穩(wěn)定的時(shí)候的電平不久可以了嗎?聽起來(lái)確實(shí)不錯(cuò),而且實(shí)際應(yīng)用起來(lái)效果也還可以。于是,各種各樣的書籍中,在提到按鍵檢測(cè)的時(shí)候,總也不忘說(shuō)道軟件消抖。就像下面的偽代碼所描述的一樣。(假設(shè)按鍵按下時(shí)候,低電平有效)

If(0 == io_KeyEnter) //如果有鍵按下了
{
Delayms(20) ; //先延時(shí)20ms避開抖動(dòng)時(shí)期
If(0 == io_KeyEnter) //然后再檢測(cè),如果還是檢測(cè)到有鍵按下
{
return KeyValue ; //是真的按下了,返回鍵值
}
else
{
return KEY_NULL //是抖動(dòng),返回空的鍵值
}
while(0 == io_KeyEnter) ; //等待按鍵釋放
}

乍看上去,確實(shí)挺不錯(cuò),實(shí)際中呢?在實(shí)際的系統(tǒng)中,一般是不允許這么樣做的。為什么呢?首先,這里的Delayms(20) , 讓微控制器在這里白白等待了20 ms 的時(shí)間,啥也沒干,考慮我在《學(xué)會(huì)釋放CPU》一章中所提及的幾點(diǎn),這是不可取的。其次while(0 == io_KeyEnter) ;更是程序設(shè)計(jì)中的大忌(極少的特殊情況例外)。任何非極端情況下,都不要使用這樣語(yǔ)句來(lái)堵塞微控制器的執(zhí)行進(jìn)程。原本是等待按鍵釋放,結(jié)果CPU就一直死死的盯住該按鍵,其它事情都不管了,那其它事情不干了嗎?你同意別人可不會(huì)同意?所以合理的分配好微控制的處理時(shí)間,是編寫按鍵程序的基礎(chǔ)。


◎消除抖動(dòng)有必要嗎?

的確,軟件上的消抖確實(shí)可以保證按鍵的有效檢測(cè)。但是,這種消抖確實(shí)有必要嗎?有人提出了這樣的疑問(wèn)。抖動(dòng)是按鍵按下的過(guò)程中產(chǎn)生的,如果按鍵沒有按下,抖動(dòng)會(huì)產(chǎn)生嗎?如果沒有按鍵按下,抖動(dòng)也會(huì)在I/O上出現(xiàn),我會(huì)立刻把這個(gè)微控制器錘了,永遠(yuǎn)不用這樣一款微控制器。所以抖動(dòng)的出現(xiàn)即意味著按鍵已經(jīng)按下,盡管這個(gè)電平還沒有穩(wěn)定。所以只要我們檢測(cè)到按鍵按下,即可以返回鍵值,問(wèn)題的關(guān)鍵是,在你執(zhí)行完其它任務(wù)的時(shí)候,再次執(zhí)行我們的按鍵任務(wù)的時(shí)候,抖動(dòng)過(guò)程還沒有結(jié)束,這樣便有可能造成重復(fù)檢測(cè)。所以,如何在返回鍵值后,避免重復(fù)檢測(cè),或者在按鍵一按下就執(zhí)行功能函數(shù),當(dāng)功能函數(shù)的執(zhí)行時(shí)間小于抖動(dòng)時(shí)間時(shí)候,如何避免再次執(zhí)行功能函數(shù),就成為我們要考慮的問(wèn)題了。這是一個(gè)仁者見仁,智者見智的問(wèn)題,就留給大家去思考吧。所以消除抖動(dòng)的目的是:防止按鍵一次按下,多次響應(yīng)。



關(guān)鍵詞: C51按鍵程序編

評(píng)論


技術(shù)專區(qū)

關(guān)閉