李其珂,付紅橋
(重慶大學光電工程學院,重慶 400030)
隨著電子信息技術的高速發展,越來越多的工業控制設備和移動終端設備得到廣泛的應用,這些設備通稱為嵌入式系統。IEEE(國際電氣和電子工程師協會)對嵌入式系統的定義為“用于控制、監視或者輔助操作機器和設備的裝置”。在這些嵌入式系統中,鍵盤作為人機交互的重要手段,是應用最為廣泛的輸入設備之一。當按鍵較少時,采用獨立式鍵盤,當按鍵較多時,采用矩陣式鍵盤。嵌入式Linux具有開源、免費、容易裁剪和良好的硬件支持等特性[1],在嵌入式計算領域得到了最為廣泛的應用。
當前,對于嵌入式系統中的矩陣鍵盤功能實現,多數應用是基于中斷方式來實現的[2-3]。按鍵事件在一個嵌入式系統中并不需要實時性很高,而采用中斷的方式來判斷按鍵是否按下的方案會把一個嵌入式系統中的按鍵事件的優先級提高,系統中其他更需要迫切處理的事件就延遲處理了,這就降低了整個系統的實時性能。本研究在基于嵌入式微處理器 AT91RM9200的基礎上,采用輪詢的機制實現了一個4×4矩陣鍵盤,并設計了矩陣鍵盤的驅動程序。
AT91RM9200是ATMEL應用最為廣泛的一款基于RISC架構的工業級ARM9處理器,主頻高達200 MHz,功耗低,片內外設非常豐富,支持嵌入式微處理器的各種常用接口,并且提供了4×32個可編程的GPIO端口[4]。本系統采用PB端口擴展了一個4×4矩陣鍵盤。其中鍵盤硬件連接示意圖如圖1所示。按鍵列陣列必須提供上拉信號,即通過4.7 K上拉電阻連接到+3.3 V電源電壓VDD上,行和列陣列都加了20 Ω電阻,防止瞬間電流過大對嵌入式微處理器I/O口造成沖擊。
按照鍵盤的構造方式,常用的鍵盤接口分為獨立式鍵盤接口和矩陣式鍵盤接口。其中,獨立式鍵盤的每個按鍵都占用嵌入式微處理器的一個I/O口,各按鍵相互獨立。使用獨立式鍵盤的優點是電路簡單、可靠,軟件編程簡單。缺點是在資源受到限制的嵌入式系統中,獨立式鍵盤對I/O口占用較多。因此,在嵌入式系統中很少使用獨立式鍵盤這種方案。
在嵌入式應用系統中,大量使用矩陣式鍵盤,它能用比較少的I/O端口驅動比較多的按鍵。圖1是嵌入式系統中最常采用的4×4矩陣鍵盤。4×4矩陣鍵盤電路由4根行線和4根列線組成,按鍵位于行、列的交叉點上。一個4×4的行列結構可以構成一個16個按鍵的鍵盤。4×4矩陣鍵盤的行和列分別和AT91RM9200處理器 的4個GPIO(General Parallel Input/Output)端口相連。顯然,在按鍵數量較多的場合,矩陣鍵盤和獨立鍵盤相比可以大大節省嵌入式系統的I/O口資源。

圖1 鍵盤硬件連接示意圖
本研究采用Linux 2.6內核作為設計的軟件平臺。隨著信息技術的不斷進步,系統的拓撲結構越來越復雜,操作系統對智能電源管理、熱插拔以及即插即用的支持要求也越來越高,Linux 2.4內核已經難以滿足這些需求。為了滿足這些新的需求,Linux 2.6內核開發了全新的總線、類、設備和驅動環環相扣的設備模型[5]。
Linux 2.6內核的設備模型如圖2所示。它是基于總線、設備和驅動的。設備掛在總線上,驅動和設備進行分離。
Linux系統將設備分成3種基本類型:字符設備、塊設備和網絡設備[6]。鍵盤屬于字符設備。許多設備都掛在總線上,但是也有設備沒有掛在總線上,本系統的矩陣鍵盤設備就沒有掛在總線上。Linux 2.6內核提供了一種platform總線機制,它是一種虛擬的總線。沒有掛在總線上的設備都可以掛在platform總線上。這種機制完全符合Linux 2.6內核的總線、設備和驅動的設備模型,并將設備和驅動進行了分離。
在Linux內核源代碼中,各種驅動程序的代碼量占據了整個Linux內核代碼的85%,這足以說明Linux設備驅動在內核代碼中的重要作用。設備驅動不僅為應用程序提供了訪問設備的機制,還為應用程序屏蔽了硬件的具體細節。在應用程序看來,硬件設備只是一個設備文件,用戶可以像操作普通的文件一樣應用程序操作硬件。

圖2 Linux設備模型
在完成4×4矩陣鍵盤接口電路的設計和掌握Linux 2.6的設備模型的基礎上,還需要編寫相應的矩陣鍵盤驅動程序。本研究采用的基于AT91RM9200處理器的平臺已經成功移植并運行了嵌入式Linux操作系統[7],因此鍵盤的驅動模塊開發就變得簡單了許多。嵌入式Linux中的驅動程序運行在內核態,屬于操作系統的范疇。驅動程序可以靜態編譯到內核,也可以以模塊方式動態加載到內核。為了方便調試,本研究選擇將按鍵驅動以動態模式加載到內核中。矩陣鍵盤驅動程序的編寫主要可分為驅動程序初始化、文件操作接口實現以及鍵盤掃描3部分。
鍵盤驅動程序屬于字符設備驅動程序的范疇。鍵盤驅動模塊主要由模塊加載函數、模塊卸載函數和模塊許可證聲明3部分組成。模塊加載函數除了完成鍵盤設備主、次設備號的申請和鍵盤設備的注冊外,還應包括硬件的初始化。下面是本文根據AT91RM9200處理器的特性[4]編寫了硬件初始化的偽代碼。


鍵盤在嵌入式系統中起到輸入作用,所以在矩陣鍵盤驅動程序的文件操作結構體中,最重要的文件操作函數是文件讀函數。在鍵盤設備文件讀函數中加入自旋鎖,確保矩陣鍵盤文件在同一時刻只被一個進程打開。因為多次按鍵可能無法被及時處理,結合實際項目的應用需求,可以利用緩沖區緩存被按下鍵的鍵碼值,直到用戶應用程序處理這一按鍵事件。本研究中的緩沖區是用一個環形隊列來實現的。緩沖區的大小可以根據具體的應用來調整,本研究設定緩沖區的大小為10個字節。當按鍵被按下后,鍵碼值就緩存到緩沖區的下一個空閑位置處,并更新緩沖區位置指針。當緩沖區滿時,丟棄此次按鍵的鍵碼值。用戶應用程序通過系統調用read()函數來讀取緩沖區的鍵碼值,驅動程序根據實際讀取鍵碼值的多少調整緩沖區的位置指針。以下是實現鍵盤讀函數keyboard_read()的偽代碼:個數;


鍵盤掃描程序是用來判斷被按下鍵的位置并取得相應的鍵碼值,然后存放到鍵碼緩沖區中。鍵盤掃描程序的實現有中斷方式和輪詢方式。本研究中利用嵌入式Linux操作系統的內核定時器實現了輪詢矩陣鍵盤的掃描方案,主要基于以下原因:一是AT91RM9200的一組GPIO端口只有一條中斷信號線,如果采用中斷方式,對于圖1的硬件設計方案必須使用4條中斷信號線才能滿足設計要求;二是因為鍵盤是嵌入式系統中的一種低速輸入設備,采用輪詢掃描鍵盤的方式就可以滿足矩陣鍵盤的輸入要求。
嵌入式Linux操作系統提供了良好的內核定時器機制,只要通過對內核定時器接口函數和數據結構進行簡單的操作,就可以實現周期性地輪詢矩陣鍵盤的狀態,并對按鍵事件進程進行處理。這一周期性時間間隔本研究指定為10 ms。本文給出的4×4矩陣鍵盤輪詢掃描程序算法流程如圖3所示。
對于消除按鍵抖動,本研究采用軟件消抖的方法。鍵盤作為輸入設備,也是共享設備。本文采用了“自旋鎖(spinlock)”機制來對共享的鍵盤實現互斥訪問。因為自旋鎖保護的代碼不能睡眠,否則就有可能發生死鎖,造成系統死機,因此消除按鍵抖動的思路是在第1次檢測到有鍵按下時,調用mdelay(KBD_JITTER)函數實現2 ms的短延時后,再次確認該鍵是否被按下,從而達到消除按鍵抖動的目的。

圖3 矩陣鍵盤掃描算法流程
利用按鍵按下抬起標志(按鍵抬起的鍵碼值是按下的鍵碼值加上0xA0),把一次完整的按鍵事件分成按下和抬起2部分。當有鍵按下未抬起的同時又有其他鍵按下,這時線程就會一直循環掃描鍵盤事件,所以能把其他的按鍵事件捕捉到并加入到環形等待隊列中。
鍵盤驅動測試主要測試鍵盤驅動能否正確地判斷被按下鍵的位置并取得相應的鍵碼值。在硬件方面,首先將PB0~PB7端口與矩陣鍵盤的行列線如圖1所示連接。然后用串口線把PC機的COM口和以AT91RM9200為核心的嵌入式目標系統的調試串口相連。在軟件方面,保證嵌入式目標系統已經能穩定運行Linux操作系統。然后利用PC機上的串口控制臺來控制嵌入式目標系統[8]。用insmod命令將編譯好的矩陣驅動模塊動態加載到內核,然后執行矩陣鍵盤測試應用程序。
當有按鍵被按下時,就會有被按下鍵的鍵碼值立即回顯在串口控制臺;當按鍵抬起時,就會有相應按鍵的鍵碼值加上0xA0立即回顯在串口控制臺。測試表明,此矩陣鍵盤驅動程序能實時、正確地判斷被按下鍵的位置。
本文介紹了基于ATMEL AT91RM9200和嵌入式Linux的4×4矩陣鍵盤驅動程序的實現方案。該驅動程序以動態模塊的方式加入內核后,通過應用程序測試證明矩陣鍵盤驅動工作準確、穩定。這一方案也對在其他嵌入式設備上擴展矩陣鍵盤具有參考價值和意義。
[1]Alex Lentnon.Embedded Linux[J].Embedded Systems,2001(5):125-128.
[2]孟桂芳.基于嵌入式Linux的矩陣鍵盤設備驅動的設計[J].蘇州大學學報:工科版,2011(4):71 -74.
[3]楊斌斌,張雪英,王玉宏.基于嵌入式Linux的矩陣鍵盤驅動程序研究與開發[J].現代電子技術,2009(2):39-41.
[4]ATMEL.AT91RM9200 User Manual[S].
[5]宋寶華.Linux設備驅動開發詳解[M].北京:人民郵電出版社,2008.
[6]Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman.Linux設備驅動程序[M].魏永明,耿岳,鐘書毅,譯.北京:中國電力出版社,2005.
[7]陳陽,徐曉光,陳躍東.基于嵌入式系統的電能采集終端設計與實現[J].重慶理工大學學報:自然科學版,2011(3):97-101.
[8]王森林,莊圣賢.基于嵌入式Linux的MP3播放器設計[J].重慶工學院學報:自然科學版,2007(3):65-68.