91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

事件驅(qū)動和鍵盤管理設(shè)計案例分析

AGk5_ZLG_zhiyua ? 來源:未知 ? 作者:劉勇 ? 2017-11-20 09:02 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

周立功教授新書《面向AMetal框架與接口編程(上)》,對AMetal框架進行了詳細介紹,通過閱讀這本書,你可以學(xué)到高度復(fù)用的軟件設(shè)計原則和面向接口編程的開發(fā)思想,聚焦自己的“核心域”,改變自己的編程思維,實現(xiàn)企業(yè)和個人的共同進步。

第四章為面向接口的編程,本文內(nèi)容包括:4.4 事件驅(qū)動和4.5 鍵盤管理。

4.4 事件驅(qū)動

>>> 4.4.1 中斷與事件驅(qū)動

1. 中斷

到目前為止,幾乎所有的程序都依賴輪詢通信。那些代碼只是一遍一遍地巡檢外圍功能部件,并在需要的時候為外圍設(shè)備提供服務(wù)??上攵?,輪詢訪問不僅消耗了大量的 MCU資源,而且將導(dǎo)致非常不穩(wěn)定的反應(yīng)時間。

為了有效地解決上述可能導(dǎo)致整個系統(tǒng)癱瘓的問題,計算機專家提出了一種“實時”的解決方案,通過“中斷”使可預(yù)見的反應(yīng)時間維持在幾微秒之內(nèi)。所謂中斷是指當 MCU 正在處理某件事情的時候,外部發(fā)生的某一“事件”請求 MCU 迅速去處理,于是 MCU 暫時中止當前的工作,轉(zhuǎn)去處理所發(fā)生的事件。當中斷服務(wù)處理完該事件以后,再回到原來被中止的地方繼續(xù)原來的工作。

但也有可能突發(fā)事務(wù)請求中斷時,可能出現(xiàn)在正常程序流程的任何地方,在正常程序流程中可以選擇響應(yīng)或不響應(yīng)這個中斷請求,突發(fā)事件的處理可能會改變整個程序的狀態(tài),從而也改變了后續(xù)的正常程序流程。

比如,在一次會議上你正在按照計劃做報告,這時手機鈴聲響了,此時,你有兩種選擇,一是你覺得正在進行的報告更重要,你可以掛斷電話或干脆關(guān)機,等會后再去處理這個來電;二是你認為這個電話很重要或很快就可處理完畢(不影響做報告),你可以暫停報告轉(zhuǎn)而接聽這個電話,當接聽完畢后,你再繼續(xù)做報告,前提是你必須記住接電話前講到哪里了,當然如果你足夠機敏的話,在這次通話中你所接收到的信息可能會改變你隨后的報告內(nèi)容。

由此可見,通過中斷方式允許系統(tǒng)在執(zhí)行主程序時可以響應(yīng)并處理其它任務(wù),進而中斷驅(qū)動系統(tǒng)給人們一種假象,MCU 可以同時執(zhí)行多個任務(wù)。而事實上 MCU 不能同時執(zhí)行 1條以上的指令,它只是暫停主程序轉(zhuǎn)去執(zhí)行其它程序,完成后再返回繼續(xù)執(zhí)行主程序。

從這個角度來看,中斷響應(yīng)非常類似于函數(shù)的調(diào)用過程。它們兩者之間的差別在于中斷的響應(yīng)是由“事件”發(fā)起的,而不像函數(shù)調(diào)用那樣,它是在主程序流程中預(yù)先設(shè)定的,中斷是系統(tǒng)響應(yīng)一些和主程序異步事件,這些事件何時將主程序中斷是預(yù)先未知的。有了中斷就可以實現(xiàn)主機與外設(shè)并行工作,支持多程序并發(fā)運行,支持實時處理功能。

2. 事件驅(qū)動

在現(xiàn)實生活中,“發(fā)生的某件事情”就是事件,事實上很多程序都對“發(fā)生的事情”做出反應(yīng)。比如,移動或點擊鼠標、按鍵、或經(jīng)過一定的時間都是基于事件的驅(qū)動程序。

事件驅(qū)動程序只是“原地不動”,什么也不做,等待有事件發(fā)生,一旦事件確實發(fā)生了,它們就會做出反應(yīng),完成所有必要的工作來處理這個事件。其實,Windows 操作系統(tǒng)就是事件驅(qū)動程序的一個很好的示例,當啟動計算機運行 Windows 時,它只是“原地不動”,不會啟動任何程序,你也不會看到鼠標光標在屏幕上移動。不過,如果你開始移動或點擊鼠標,就會有情況發(fā)生。

為了讓事件驅(qū)動程序“看到”有事件發(fā)生,它必須“尋找”這些事件,程序必須不斷地掃描計算機內(nèi)存中用于事件發(fā)生的部分,即只要程序在運行就會不斷尋找事件。顯然,只要移動或點擊了鼠標或按下了按鍵,就會發(fā)生事件,這些事件在哪里呢?比如,在內(nèi)存中存儲事件的部分就是事件隊列,事件隊列就是發(fā)生的所有事件的列表,這些事件按它們發(fā)生的順序排列。

如果需要編寫一個游戲,則程序必須知道用戶什么時候按下一個按鍵或移動了鼠標。而這些按鍵動作、點擊或移動鼠標都是事件,而且程序必須知道如何應(yīng)對這些事件,它必須處理事件,程序中處理某個事件的部分稱為 事件處理器。而事實上并不是發(fā)生的每一個事件都要處理,比如,在桌面移動鼠標就會產(chǎn)生成百上千個事件,因為事件循環(huán)運行得非???。每一個瞬間即使鼠標只是移動了一點點,也會生成一個新的事件。不過你的程序可能并不關(guān)心鼠標的每一個小小的移動,它可能只關(guān)心用戶什么時候點擊某個部分,因此你的程序可以忽略鼠標移動事件,只關(guān)注鼠標點擊事件。

事件驅(qū)動程序中,對于所關(guān)心的各種事件會有相應(yīng)的事件處理器。如果你有一個游戲使用鍵盤上的方向來控制一艘船的移動,可能要為 keyDown 事件寫一個處理器;相反,如果使用鼠標控制這艘船,就可能為 mouseMove 事件寫一個事件處理器。

另一種有用的事件是軟件定時器事件,定時器會按設(shè)定的間隔生成事件,就像鬧鐘一樣,如果設(shè)定好鬧鐘,并將鬧鐘打開,每天它都會在固定的時刻響起來。比如,(宏觀上)同時處理兩個事件。其中,一個為鍵盤輸入事件,另一個為時間事件,用于顯示運行的時間,每秒顯示一次。

顯然,可以在 main()函數(shù)設(shè)置一個循環(huán),依次檢查是否有鍵盤輸入和時間是否到 1 秒?其實都可以直接調(diào)用固定的函數(shù)來實現(xiàn)“鍵盤輸入處理代碼”和“時間處理代碼”,但這樣不夠靈活,此時可以用中斷機制來實現(xiàn),即由硬件來實現(xiàn)對事件的檢測并調(diào)用指定的函數(shù),這樣一來使用注冊回調(diào)函數(shù)機制也就成為了必然。而注冊回調(diào)函數(shù)就是事先用一個函數(shù)指針變量保存指定的函數(shù),然后在事件發(fā)生時,通過這個函數(shù)指針變量調(diào)用指定的函數(shù)。

>>>4.4.2 軟件定時器

我們知道,數(shù)碼管顯示主要做兩件事,其一,每隔 5ms 調(diào)用一次 digitron_disp_scan()動態(tài)掃描顯示函數(shù),其次,當需要改變顯示內(nèi)容時,則調(diào)用緩沖區(qū)操作接口,修改緩沖區(qū)中的內(nèi)容。由于 MCU 設(shè)計了類似于鬧鐘那樣的特定性的周期性的中斷時鐘節(jié)拍源,因此由時鐘節(jié)拍源實現(xiàn)的定時器也是一個周期性的定時器,并產(chǎn)生周期性的中斷,這個中斷可以看做系統(tǒng)心臟的脈動。即當計數(shù)值等于定時時間時,則定時器立即觸發(fā)中斷,計數(shù)器重新開始計數(shù),如此周而復(fù)始循環(huán)計數(shù)。

顯然,可以使用定時器的周期性的中斷實現(xiàn)自動掃描顯示,即每隔 5ms 觸發(fā)中斷自動調(diào)用 digitron_disp_scan(),這樣就可以將 MCU 解放出來執(zhí)行其它的任務(wù),從而得到更好的性能,其相應(yīng)的接口函數(shù)詳見表 4.3。程序員先調(diào)用軟件定時器函數(shù),然后等待操作完成。通常程序員提供一個由函數(shù)指針指定的回調(diào)函數(shù),當操作完成后,中斷系統(tǒng)會調(diào)用回調(diào)函數(shù)。

表 4.3 軟件定時器接口函數(shù)

1. am_softimer_t 類型

從面向?qū)ο蟮慕嵌葋砜矗愊喈斢?C 語言的結(jié)構(gòu)體,這里的 am_softimer_t 是用 typedef自定義的一個對用戶隱藏的結(jié)構(gòu)體類型。即:

在使用軟件定時器時,需要使用該類型定義一個軟件定時器實例(對象),實例的本質(zhì)是定義一個結(jié)構(gòu)體變量。比如:

顯然,對象是類型的實例,即 timer 是 am_softimer_t 類型的一個實例。

2. 初始化軟件定時器

事先將指定的函數(shù)保存在函數(shù)指針 p_func 中(注冊),當定時時間到時,則通過 p_func調(diào)用指定的函數(shù),即注冊函數(shù)回調(diào)機制。

其中的 p_timer 為使用 am_softimer_t 類型定義的軟件定時器實例,當定時時間到,則調(diào)用 p_func 指向的函數(shù)(注冊回調(diào)函數(shù)),am_pfnvoid_t 是 AMetal 聲明的函數(shù)指針類型,其定義(am_types.h)如下:

由此可見,p_func 指向的函數(shù)類型是無返回值,具有一個 void*型參數(shù)的函數(shù)。p_arg為用戶自定義的參數(shù),在定時時間到調(diào)用回調(diào)函數(shù)時,會將此處設(shè)置的 p_arg 作為作為參數(shù)傳遞給回調(diào)函數(shù);如果不使用此參數(shù),則設(shè)置為 NULL。如果返回 AM_OK,說明軟件定時器初始化成功;如果返回-AM_EINVAL,說明由于參數(shù)錯誤導(dǎo)致初始化失敗。初始化函數(shù)的使用范例詳見程序清單 4.26。

程序清單 4.26 am_softimer_init ()函數(shù)范例程序

其中的 am_softtimer_init()函數(shù)(A)與用戶自定義的任務(wù)函數(shù)(C)同屬于上層模塊的函數(shù),timer_callback()函數(shù)(B)為下層模塊的函數(shù)。由于事先已經(jīng)將 timer_callback()的地址 time_callback 保存在 p_func 中了,因此,當 am_softtimer_init()調(diào)用 timer_callback()時,僅需將用戶自定義的任務(wù)函數(shù)的入口地址作為實參傳遞給 timer_callback()的形參,即可通過函數(shù)指針變量 p_arg 在某個時刻回調(diào)用戶自定義的任務(wù)函數(shù),即在函數(shù) A 調(diào)用函數(shù) B 中直接調(diào)用回調(diào)函數(shù) C。即只要在每次調(diào)用 timer_callback()時,給出不同的函數(shù)名作為實參,即可回調(diào)相應(yīng)的函數(shù),卻不必修改 timer_callback()。

3. 啟動軟件定時器

啟動定時器并設(shè)置定時時間(單位 ms),然后定時器開始計數(shù)。當計數(shù)值等于定時時間時,則定時器立即觸發(fā)中斷,計數(shù)器重新開始計數(shù),如此周而復(fù)始循環(huán)計數(shù)。當定時器觸發(fā)中斷時,則程序跳轉(zhuǎn)到調(diào)用 am_softimer_init()時 p_func 指向的函數(shù),其函數(shù)原型為:

p_timer 為使用 am_softimer_t 類型定義的軟件定時器實例,ms 為定時時間,單位 ms。如果返回 AM_OK,說明啟動定時器成功;如果返回-AM_EINVAL,說明失敗參數(shù)錯誤。設(shè)置定時器以實現(xiàn)數(shù)碼管自動掃描顯示的代碼詳見程序清單 4.27。

程序清單 4.27 自動掃描顯示實現(xiàn)

程序中,digitron_softimer_set()函數(shù)初始化并啟動了一個軟件定時器,并在定時器回調(diào)函數(shù)中調(diào)用了數(shù)碼管掃描函數(shù),進而實現(xiàn)了數(shù)碼管自動掃描。

為了更方便的使用自動掃描,可以將 digitron_softimer_set()合并到 digitron_init()中,形成一個新的 digitron_init_with_softimer(),當用戶需要數(shù)碼管初始化后自動掃描時,只需調(diào)用該帶軟件定時器的初始化函數(shù)即可,詳見程序清單 4.28。

程序清單 4.28 digitron1.h 文件內(nèi)容

如程序清單 4.29 所示為再次迭代的 0~59 秒循環(huán)顯示程序。

程序清單 4.29 0~59 秒計數(shù)器范例程序(3)

既然程序是每隔 1s 計數(shù)器加 1 后更新緩沖區(qū)數(shù)據(jù)的,那么同樣可以使用軟件定時器實現(xiàn)每秒加 1 的操作,迭代后的代碼詳見程序清單 4.30。

程序清單 4.30 0~59 秒計數(shù)器范例程序(4)

當啟動軟件定時器后,秒計數(shù)器加1和更新緩沖區(qū)數(shù)據(jù)的工作自動在timer_sec_callback()函數(shù)中完成,不再需要主程序干預(yù)。現(xiàn)在 while(1)主循環(huán)什么事情都不用做,同樣實現(xiàn)了 0~59的循環(huán)顯示。這樣一來,數(shù)碼管就會獨立地工作了,那么在 while(1)主循環(huán)中,就可以直接去做其它事情。以后遇到“每隔一定時間做某件事”的問題,均可使用軟件定時器來實現(xiàn)。

雖然用軟件定時器實現(xiàn)自動掃描顯示的方法非常巧妙,流程也更加清晰,且程序還可以去做其它的事情,但卻是以犧牲程序空間為代價的,即軟件定時器要占用一個硬件定時器,以及 438 個字節(jié)的 Flash 和 12 個字節(jié)的 RAM。同時在使用軟件定時器時,由于新建一個軟件定時器必須定義一個定時器實例,每個定時器實例還要占用 24 字節(jié),因此要根據(jù)硬件資源做出取舍。

4. 關(guān)閉軟件定時器

當軟件定時器關(guān)閉時,如果再次啟動,則調(diào)用 am_softimer_start()重新啟動。即:

其中的 p_timer 為使用 am_softimer_t 類型定義的軟件定時器實例,如果返回 AM_OK,說明停止定時器;如果返回-AM_EINVAL,即參數(shù)錯誤導(dǎo)致關(guān)閉失敗,詳見程序清單 4.31。

程序清單 4.31 am_softimer_stop ()范例程序

現(xiàn)在不妨在程序清單 4.30 的基礎(chǔ)上,再增加一個小功能,即每秒加一、蜂鳴器“嘀”一聲,詳見程序清單 4.32。

程序清單 4.32 0~59 秒計數(shù)器+蜂鳴器綜合范例程序(1)

通過運行發(fā)現(xiàn),雖然計數(shù)器在每秒加 1 時,蜂鳴器也會發(fā)出“嘀”的一聲,但數(shù)碼管的某位卻會熄滅一下。如果覺得看起來還不夠明顯,不妨將蜂鳴器的鳴叫時間增加到 500ms。奇怪!為何連顯示都不正常了呢?

雖然此前在 main()函數(shù)的 while(1)主循環(huán)中也使用了延時,但在主程序的延時期間,軟件定時器定時時間到而產(chǎn)生的中斷事件是可以搶占 MCU 的,所以不會影響其它事件的繼續(xù)運行。如果在中斷環(huán)境中調(diào)用 buzzer_beep(),程序必須等到蜂鳴器鳴叫結(jié)束后才會返回,這樣一來就會使回調(diào)函數(shù)產(chǎn)生 100ms 的延時,從而導(dǎo)致 MCU 被完全占用,不僅 while(1)主循環(huán)無法執(zhí)行,而且連其它的中斷事件也無法執(zhí)行。比如,另一個軟件定時器中的數(shù)碼管動態(tài)掃描也就無法執(zhí)行了,所以在這 100ms 時間內(nèi),無法實現(xiàn)數(shù)碼管動態(tài)掃描,于是只有一個數(shù)碼管顯示,另外一個數(shù)碼管無法顯示而處于熄滅的狀態(tài)。

在這種情況下,應(yīng)盡可能地將相應(yīng)功能設(shè)計為異步模式,即啟動軟件定時器,設(shè)定蜂鳴器鳴叫時間,打開蜂鳴器,函數(shù)立即返回。待定時時間到,則自動調(diào)用回調(diào)函數(shù),然后在回調(diào)函數(shù)中關(guān)閉蜂鳴器并停止定時器。這就是使用軟件定時器實現(xiàn) buzzer_beep_async()的由來,異步模式的優(yōu)點是無需等待,函數(shù)立即返回,即可在任意地方調(diào)用該函數(shù)了,再也不會因為

延時而帶來副作用,詳見程序清單 4.33。

程序清單 4.33 實現(xiàn)蜂鳴器異步鳴叫函數(shù)

基于此,將 buzzer_beep_async()添加到 buzzer.h 以利于復(fù)用,詳見程序清單 4.34。

程序清單 4.34 0~59 秒計數(shù)器+蜂鳴器綜合范例程序(2)

4.5 鍵盤管理

>>> 4.5.1 獨立按鍵

1. 消抖方法

對于質(zhì)量不太好或者長期使用簧片氧化磨損的按鍵來說,常常會產(chǎn)生一種被稱為“抖動”的現(xiàn)象。如圖 4.12(a)所示為單觸點按鍵的無消抖電路,當按鍵未按下時,則輸出 Y 為高電平;當按下時,則輸出 Y 為低電平。但由于按鍵的機械特性和人手指的不穩(wěn)定性等綜合因素,致使按鍵盤剛按下的瞬間,因接觸不良而產(chǎn)生的反復(fù)跳動現(xiàn)象,即“抖動”,同樣在按鍵釋放的瞬間也可能產(chǎn)生“抖動”,結(jié)果輸出 Y 在這一瞬間產(chǎn)生了多個窄脈沖干擾,這些脈沖信號的寬度一般可達毫秒,詳見圖 4.12 (b)。

圖 4.12 無消抖按鍵電路及波形

“抖動”的脈沖寬度一般有幾十到幾百微秒,但也可能達到毫秒級,這對運行速度很快的數(shù)字電路會產(chǎn)生很大的影響。如果將發(fā)生“抖動”現(xiàn)象的按鍵連接到計數(shù)電路的時鐘輸入端,則檢測到每按一次鍵都會產(chǎn)生一串極不穩(wěn)定的脈沖。

對實際的產(chǎn)品來說,按鍵在長時間的使用中永不產(chǎn)生“抖動”是不可能的,但只要預(yù)防可能產(chǎn)生的“抖動”即可。抖動其實只持續(xù)了一小段時間,軟件延時就是在按鍵產(chǎn)生“抖動”的這段時間里,用“拖延時間”的方法避開,從而消除因“抖動”而產(chǎn)生的錯誤信號,其示意圖詳見圖 4.13。在按下鍵的瞬間啟動定時器開始延時,延時 td 時間后再判斷按鍵是否仍然按下,若仍按下則本次按鍵有效,否則本次按鍵無效。延時消抖由于過程比較復(fù)雜,比較適合用軟件實現(xiàn),因此稱為軟件消抖。

圖 4.13 延時消抖

2. 電路原理

一般來說,在用法上按鍵可分為獨立按鍵和矩陣鍵盤兩大類。LPC824 的 P0_10、P0_11是標準的開漏結(jié)構(gòu),無內(nèi)部上拉電阻,因此連接按鍵時必須加上拉電阻。其它的 14 個 GPIO口均有可編程使能的內(nèi)部上拉電阻,雖然 MCU 內(nèi)部有幾十 KΩ以上的上拉電阻,但均屬于弱上拉,所以在實際的應(yīng)用中,一般都會外接一個阻值適中的上拉電阻,以提高可靠性。

對于獨立按鍵來說,要求比較簡單,既不考慮多個鍵同時按下,也不考慮長按的情況。僅識別是否有鍵按下的情況,即有鍵按下一次執(zhí)行一次操作。如圖 4.14 所示是一個獨立按鍵電路圖,只要將 AM824-Core的 J14_1 與 J14_2 短接,則 KEY 鍵接入 PIO0_1。

圖 4.14 獨立按鍵電路圖

由于一次按鍵的時間通常都是上百毫秒,相對于 MCU 來說是很長的,因此不需要時時刻刻不斷地檢測按鍵,只需要每隔一定的時間(如 10ms)檢測 GPIO 的電平即可。其檢測方法如下(1 表示高電平、0 表示低電平):

(1)當無鍵按下時,由于 PIO0_1 內(nèi)部自帶弱上拉電阻,因此 PIO0_1 為 1;

(2)當 KEY 按下時,則 PIO0_1 為 0。在下一次掃描(延時 10ms 去抖動)后,如果PIO0_1 為 1,說明錯誤觸發(fā);如果 PIO0_1 還是 0,說明確實有鍵按下,執(zhí)行相應(yīng)的操作;

(3)當 KEY 釋放時,則 PIO0_1 為 1,在下一次掃描(延時 10ms 去抖動)后,如果PIO0_1 為 0,說明錯誤觸發(fā);如果 PIO0_1 還是 1,說明按鍵已經(jīng)釋放,執(zhí)行相應(yīng)的操作。

3. Key 軟件包

AMetal 提供了獨立按鍵初始化和按鍵掃描函數(shù)接口(key1.h),詳見程序清單 4.35。

程序清單 4.35 key1.h 接口

如程序清單 4.36 所示為獨立按鍵的范例程序,如果有鍵按下,則蜂鳴器“嘀”一聲;當按鍵釋放后,則 LED0 翻轉(zhuǎn)。

程序清單 4.36 獨立按鍵范例程序

顯然,每隔 10ms 調(diào)用一次 key1_scan(),即可根據(jù) key_return 的值判斷按鍵事件的產(chǎn)生,但這又是“每隔一段時間做某事”。如果使用軟件定時器定時自動掃描,則無需在 while(1)中每隔 10ms 調(diào)用一次 key1_scan(),詳見程序清單 4.37。

程序清單 4.37 添加軟件定時器后的按鍵范例程序

程序中新增了一個初始化軟件定時器 key1_softimer_set(),并啟動軟件定時器以 10ms的時間間隔,通過 key1_softimer_callback()回調(diào) key1_scan()實現(xiàn)按鍵掃描。當按鍵事件發(fā)生(返回值不為 0xFF)時,則調(diào)用 key1_process()按鍵處理程序,根據(jù)掃描得到的返回值判斷按鍵事件的發(fā)生。在 key1_process()按鍵處理程序中,當有鍵按下時,蜂鳴器“嘀”一聲;當按鍵釋放時,LED0 翻轉(zhuǎn)。由于 key1_process()是在中斷環(huán)境的回調(diào)函數(shù)中調(diào)用的,因此不能出現(xiàn)阻塞式語句,必須調(diào)用異步模式下的 buzzer_beep_async()。

在這里,與軟件定時器相關(guān)的代碼直接放在主程序中,而在實際使用時,更希望將實現(xiàn)和聲明分別放在 key1.c 和 key1.h 中,因此需要增加一個接口函數(shù):

雖然按鍵與數(shù)碼管都可以使用軟件定時器實現(xiàn)自動掃描,但它們之間卻存在一定的差異,數(shù)碼管只要自動掃描即可,但對于按鍵自動掃描,當掃描到按鍵事件發(fā)生時,還必須通知應(yīng)用程序做相應(yīng)的處理。而實際上在封裝模塊時,并不知道應(yīng)用程序要做什么事,唯一的辦法是采用注冊回調(diào)機制。當按鍵事件發(fā)生時,調(diào)用相應(yīng)的注冊函數(shù)。如果需要使用軟件定時器,則在初始化時注冊一個函數(shù),以便按鍵事件發(fā)生時調(diào)用。定義回調(diào)函數(shù)類型為:

重新定義帶軟件定時器的初始化函數(shù)類型為:

為了便于使用,將上述函數(shù)聲明和回調(diào)函數(shù)類型定義添加到程序清單 4.38 所示的 key1.h中,其相關(guān)實現(xiàn)代碼添加到程序清單 4.39 所示的 key1.c 中。

程序清單 4.38 key1.h 文件內(nèi)容

程序清單 4.39 新增使用軟件定時器自動掃描的程序(key1.c)

當有鍵按下時,則蜂鳴器“嘀”一聲;當按鍵釋放時,則 LED0 翻轉(zhuǎn),經(jīng)過迭代后的代碼詳見程序清單 4.40。

程序清單 4.40 使用軟件定時器自動進行按鍵掃描范例程序

>>> 4.5.2 矩陣鍵盤

獨立按鍵必須占用一個 I/O 口,當按鍵數(shù)目較多時,這種每個按鍵占用一個口的方法就顯得很浪費了。如何用盡可能少的 I/O 口去管理較多的按鍵呢?矩陣形式鍵盤電路就是使用最多的一種,如圖 4.15 所示就是一種典型的矩陣式 2×2 鍵盤電路。采用矩陣鍵盤方式進行排列,其中 KR0、KR1 為行線,KL0、KL1 為列線。

圖 4.15 2×2 矩陣鍵盤

該接法將口線分成行線(row)和列線(column),如果將它變成比較容易理解的拓撲結(jié)構(gòu),就是兩組垂直交叉的平行線,每個交叉點就是一個按鍵位置,按鍵的兩端分別接在行線和列線上。其最大優(yōu)點是組合靈活,假如有16 個 I/O 可用于擴展做鍵盤電路,我們可以將它接成 6×10、5×11 或 8×8 等多種接法,當然,使用效率最高的是 8×8 的接法,它最多可實現(xiàn) 64 個按鍵。

MiniPort-Key 按鍵模塊集成了 4 個按鍵,通過 MiniPort B(排母)與 AM824-Core 相連,同時引出其余不用的 I/O,實現(xiàn)模塊的橫向堆疊,其對應(yīng) AM824-Core 的 MiniPort 接口的 J4的功能定義詳見圖 4.16。

圖 4.16 按鍵模塊實物與接口定義圖

2×2 的矩陣鍵盤共有 4 個按鍵,分別為 KEY0~KEY3。KR0、KR1 為行線(row),KL0、KL1 為列線(column)。假設(shè)選擇 KL0、KL1 為輸入,當無鍵按下時,由于內(nèi)部弱上拉作用,此時讀取電平為高電平。當 KEY0 按下時,KL1 依然為高電平,而 KL0 在 KR0 輸出低電平時就會得到低電平。顯然,只有 KR0、KR1 輸出為低電平時,KL0、KL1 才能得到低電平,這就是逐行掃描鍵盤的方法,即行線為輸出,列線為輸入,每次掃描一行,掃描該行時,對應(yīng)行線輸出為低電平,其余行線輸出為高電平,然后讀取所有列線的電平,若有列線讀到低電平,則表明該行與讀到低電平的列對應(yīng)的交叉點有按鍵按下。逐列掃描法恰好相反,其列線為輸出,行線為輸入,但基本原理還是一樣的。AMetal 針對矩陣鍵盤提供了相應(yīng)的 matrixkey.h 接口,詳見程序清單 4.41。

程序清單 4.41 matrixkey.h 接口

如程序清單4.42所示是使用上述接口的范例程序,即當有鍵按下時,蜂鳴器在發(fā)出“嘀”的一聲的同時,通過 LED0 和 LED1 的組合顯示按鍵編號。比如,KEY0 鍵按下時,兩個 LED燈均熄滅。KEY1 按下時顯示 01,即 LED0 亮,LED1 熄滅,依此類推。

程序清單 4.42 矩陣鍵盤范例程序

為了節(jié)省引腳,還可以將數(shù)碼管與矩陣鍵盤結(jié)合起來使用,如圖4.17 所示的數(shù)碼管的 2個 com 端與矩陣鍵盤的列線是復(fù)用的,PIO0_17與 PIO0_23 既是數(shù)碼管的 com0、com1,又是矩陣鍵盤的列線 KL0、KL1這樣設(shè)計反而節(jié)省了引腳。作為鍵盤掃描時需將列線配置為輸入,作為數(shù)碼管掃描時需將 com 端設(shè)置為輸出。

圖 4.17 LED 顯示器電路

為了不影響數(shù)碼管的顯示,在鍵盤掃描結(jié)束后,必須將管腳恢復(fù)為輸出狀態(tài)。這是由

函數(shù)實現(xiàn)的。鍵盤掃描只需要每隔 10ms 進行一次,而數(shù)碼管掃描需要每隔 5ms 進行一次,當它們同時使用時,可以在按鍵掃描的 10ms 內(nèi)進行 2 次數(shù)碼管掃描。

利用 4 個按鍵和數(shù)碼管,實現(xiàn)一個按鍵調(diào)節(jié)值的小應(yīng)用,各個按鍵的功能定義如下:

  • KEY0:進入設(shè)置狀態(tài)。點擊后進入設(shè)置狀態(tài),默認個位不斷閃爍,再次點擊后回到正常運行狀態(tài);

  • KEY2:切換當前調(diào)節(jié)的位。當進入設(shè)置狀態(tài)后,當前調(diào)節(jié)的位會不斷地閃爍。點擊該鍵可以切換當前調(diào)節(jié)的位,由個位切換到十位,或由十位切換到個位;

  • KEY1:也稱為+1 鍵,將當前正在閃爍的位的值加 1;

  • KEY3:也稱為-1 鍵,將當前正在閃爍的位的值減 1。

其相應(yīng)的范例程序詳見程序清單 4.43。

程序清單 4.43 矩陣鍵盤+數(shù)碼管范例程序(2)


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 定時器
    +關(guān)注

    關(guān)注

    23

    文章

    3368

    瀏覽量

    123902
  • 周立功
    +關(guān)注

    關(guān)注

    38

    文章

    130

    瀏覽量

    38747

原文標題:周立功:面向接口的編程——事件驅(qū)動和鍵盤管理

文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    RGB顯示驅(qū)動MCU單片機—CH643鍵盤應(yīng)用方案

    隨著電競外設(shè)與智能硬件市場的持續(xù)升溫,鍵盤產(chǎn)品已不再局限于簡單的輸入功能,RGB燈光效果與無線快充體驗逐漸成為用戶關(guān)注的焦點。CH643作為一款專為RGB顯示驅(qū)動設(shè)計的MCU,憑借其高度集成的特性,為鍵盤及面板應(yīng)用提供了全新的技
    的頭像 發(fā)表于 03-13 15:04 ?80次閱讀
    RGB顯示<b class='flag-5'>驅(qū)動</b>MCU單片機—CH643<b class='flag-5'>鍵盤</b>應(yīng)用方案

    TH2839阻抗分析儀在LED驅(qū)動集成電路寄生參數(shù)測試分析中的應(yīng)用

    電阻)對高頻響應(yīng)、電磁兼容性及熱管理具有顯著影響。因此,精準提取和分析這些寄生參數(shù),成為優(yōu)化電路設(shè)計、提升系統(tǒng)可靠性的關(guān)鍵環(huán)節(jié)。TH2839系列阻抗分析儀憑借其高精度、寬頻帶和多功能特性,為LED
    的頭像 發(fā)表于 02-26 16:48 ?499次閱讀
    TH2839阻抗<b class='flag-5'>分析</b>儀在LED<b class='flag-5'>驅(qū)動</b>集成電路寄生參數(shù)測試<b class='flag-5'>分析</b>中的應(yīng)用

    【開源鍵盤合集】60%、100%、120%多種鍵盤布局,你選哪種?

    “本合集收錄了多款使用KiCad設(shè)計的開源客制化鍵盤,是時候復(fù)刻一把了”點擊跳轉(zhuǎn),可獲取設(shè)計文件掃碼入群,失效請加微信:opensrc_KLin本合集涵蓋了60%、100%、120%多種配列鍵盤
    的頭像 發(fā)表于 01-27 08:05 ?1709次閱讀
    【開源<b class='flag-5'>鍵盤</b>合集】60%、100%、120%多種<b class='flag-5'>鍵盤</b>布局,你選哪種?

    Linux驅(qū)動開發(fā)的必備知識

    驅(qū)動框架進行開發(fā)。 6、調(diào)試技能: 掌握內(nèi)核調(diào)試工具,如 KDB、KGDB、printk 等。 能夠分析內(nèi)核日志,定位驅(qū)動程序中的問題。
    發(fā)表于 12-04 07:58

    FZH217 帶鍵盤掃描接口的大筆段 LED 驅(qū)動控制專用電路 原廠技術(shù)支持

    型號:FZH217廠商:深圳市方中禾科技有限公司(Premier Chip Limited)FZH217 是帶鍵盤掃描接口的大筆段 LED 驅(qū)動控制專用電路,內(nèi)部集成有 MCU 數(shù)字接口、數(shù)據(jù) 鎖存
    發(fā)表于 12-03 11:01

    FZH216 帶鍵盤掃描接口的大筆段 LED 驅(qū)動控制專用電路

    型號:FZH216廠商:深圳市方中禾科技有限公司(Premier Chip Limited)FZH216 是帶鍵盤掃描接口的大筆段 LED 驅(qū)動控制專用電路,內(nèi)部集成有 MCU 數(shù)字接口、數(shù)據(jù)鎖存器
    發(fā)表于 12-02 11:57

    FZH183 帶鍵盤掃描接口的LED(發(fā)光二極管顯示器)驅(qū)動控制專用電路--方中禾科技

    型號:FZH183FZH183是帶鍵盤掃描接口的LED(發(fā)光二極管顯示器)驅(qū)動控制專用電路,內(nèi)部集成有MCU 數(shù)字接口、數(shù)據(jù)鎖存器、LED 高壓驅(qū)動、鍵盤掃描等電路。主要應(yīng)用于冰箱、空
    發(fā)表于 11-28 09:31

    原廠 FZH1697 帶鍵盤掃描接口的LCD驅(qū)動控制專用電路

    )FZH1697是一種帶鍵盤掃描接口的LCD驅(qū)動控制專用電路,內(nèi)部集成有MCU 數(shù)字接口、數(shù)據(jù)鎖存器、LCD驅(qū)動、鍵盤掃描、幻彩背光驅(qū)動等電
    發(fā)表于 11-07 09:43

    ?LP3958 照明管理單元芯片技術(shù)文檔總結(jié)

    LP3958 是一款用于便攜式應(yīng)用的照明管理單元。它用于駕駛 顯示背光和鍵盤 LED。該設(shè)備可以驅(qū)動 5 個單獨連接的 LED 串,并帶有 高壓升壓轉(zhuǎn)換器。 鍵盤 LED
    的頭像 發(fā)表于 09-05 15:10 ?849次閱讀
    ?LP3958 照明<b class='flag-5'>管理</b>單元芯片技術(shù)文檔總結(jié)

    鍵盤常見問題的解決方法

    用戶點擊輸入框時,軟鍵盤默認彈出。但在特定場景下,需要對軟鍵盤的彈出和收起進行控制,如點擊空白區(qū)域收起軟鍵盤,進入頁面時輸入框主動獲焦。開發(fā)者還需根據(jù)軟鍵盤狀態(tài)和高度調(diào)整頁面布局。
    的頭像 發(fā)表于 09-04 09:11 ?841次閱讀

    鍵盤薄膜高彈UV膠則是一種特殊改性的UV固化膠,用于薄膜鍵盤按鍵彈性體的部分或高彈性密封

    薄膜鍵盤是一種常見的鍵盤類型,它使用薄膜作為按鍵的觸發(fā)器。而鍵盤薄膜高彈UV膠則是一種特殊改性的UV固化膠,用于薄膜鍵盤按鍵彈性體的部分或高彈性密封。薄膜
    的頭像 發(fā)表于 08-26 10:03 ?997次閱讀
    <b class='flag-5'>鍵盤</b>薄膜高彈UV膠則是一種特殊改性的UV固化膠,用于薄膜<b class='flag-5'>鍵盤</b>按鍵彈性體的部分或高彈性密封

    HarmonyOS應(yīng)用自定義鍵盤解決方案

    自定義鍵盤是一種替換系統(tǒng)默認鍵盤的解決方案,可實現(xiàn)鍵盤個性化交互。允許用戶結(jié)合業(yè)務(wù)需求與操作習(xí)慣,對按鍵布局進行可視化重構(gòu)、設(shè)置多功能組合鍵位,使輸入更加便捷和舒適。在安全防護層面,自定義鍵盤
    的頭像 發(fā)表于 06-05 14:19 ?2439次閱讀

    BMS 管理方案 NRF52833

    電池的智能化管理,同時提高電池使用壽命。通過 BMS 管理方案,結(jié)合手機APP、服務(wù)器數(shù)據(jù)統(tǒng)計分析,實現(xiàn)對電池系統(tǒng)的高效、安全和可靠管理,為相關(guān)應(yīng)用提供堅實的動力保障。 二、系統(tǒng)架構(gòu)
    發(fā)表于 04-09 16:06

    新能源汽車驅(qū)動電機專利信息分析

    采用Thomson Innovation專利檢索分析平臺搜集整理驅(qū)動電機相關(guān)專利,通過分析國內(nèi)外驅(qū)動電機專利的 申請時間趨勢、國別分布、申請人排名、技術(shù)熱點分布以及國內(nèi)專利省市分布,了
    發(fā)表于 03-21 13:39