張星,張睿智,郝琛,姚美菱
(石家莊郵電職業(yè)技術(shù)學(xué)院 智能工程系,河北石家莊,050021)
矩陣鍵盤模塊是工業(yè)電子產(chǎn)品常用的輸入設(shè)備,比如需要輸入簡單數(shù)字字符的快遞柜、存包柜等,如圖1所示,常見的矩陣鍵盤樣式有4×3(12 鍵)和4×4(16 鍵)的,鍵盤材質(zhì)有薄膜鍵盤型、直插按鍵型、ABS 外殼鍵盤型等。
圖1 多種材質(zhì)樣式的矩陣鍵盤
矩陣鍵盤由于按鍵機(jī)械特性及電路構(gòu)成結(jié)構(gòu)等原因,在按鍵按下及松開瞬間觸點電壓跳變會引起現(xiàn)按鍵自身及按鍵之間的電壓抖動,造成按鍵誤判錯誤輸入。按鍵輸入過程包括去除抖動和按鍵識別,去除抖動可以通過程序設(shè)計和硬件設(shè)計兩種方法實現(xiàn)。作者在設(shè)計快遞柜產(chǎn)品使用無硬件去抖的矩陣鍵盤時發(fā)現(xiàn),采用順序掃描的按鍵識別方法,一定概率會出現(xiàn)按鍵誤判錯誤輸入,影響了使用者體驗,經(jīng)實驗發(fā)現(xiàn)不同材質(zhì)樣式的矩陣鍵盤出現(xiàn)錯誤的概率也不同,塑料矩陣鍵盤按鍵時震動較大,出現(xiàn)誤判錯誤的概率高一些。
如圖2所示,智能快遞柜中使用矩陣鍵盤,用戶在通過按鍵輸入操作完成取件。通過矩陣鍵盤輸入的數(shù)字及字符在ST7920 液晶屏(12864 字庫型)上顯示,因快遞柜主控板使用的STM32 單片機(jī)主頻高,片上資源豐富,快遞柜系統(tǒng)任務(wù)占用不高,可以通過提高矩陣鍵盤占用單片機(jī)運(yùn)行資源的方法減少按鍵誤判的概率,提高鍵盤輸入流暢度,改善用戶使用體驗。
圖2 矩陣鍵盤在智能快遞柜中的使用
4 行4 列式矩陣鍵盤的電路仿真原理如圖3所示,按鍵組成行列矩陣形式,水平方向的行線和垂直方向的列線,在兩條線交叉的地方?jīng)]有直接相連,通過1個機(jī)械按鍵控制交叉觸點的連接或斷開,4 行4 列式矩陣鍵盤能夠組合成16個按鍵輸入。
圖3 4×4矩陣鍵盤原理圖
矩陣鍵盤的行線和列線分別連接STM32 單片機(jī)的4個GPIO口,共計8 條線,如果是按鍵直連單片機(jī)GPIO口,16 鍵鍵盤需要占用16個GPIO口,將多占用1 倍IO 資源。顯然,使用矩陣鍵盤的優(yōu)勢是減少GPIO口的占用,但隨之而來的是造成按鍵識別難度增加,按鍵間的相互干擾增大,需要設(shè)計出相對復(fù)雜的識別及去抖程序。
(1)行列順序掃描按鍵識別法
行列順序掃描按鍵識別法的基本思路是,行線依次置零,按照列線順序讀取,當(dāng)列線讀到零,置零的行和讀到零的列交叉的位置就是被按下的按鍵。
首先將所有行列對應(yīng)的GPIO口設(shè)置為高電平,隨后將第1 行對應(yīng)GPIO口設(shè)置為低電平,依次讀取1 到4 列對應(yīng)GPIO口數(shù)據(jù),如果列線GPIO口的數(shù)據(jù)等于零(相當(dāng)于低電平),表示第1 行當(dāng)前列有按鍵按下,所有行列對應(yīng)的GPIO口設(shè)置為高電平,程序跳出循環(huán)返回。如果沒有讀到數(shù)據(jù)零,則將2 行對應(yīng)GPIO 引腳設(shè)置為低電平,依次讀取1 到4 列對應(yīng)GPIO口數(shù)據(jù),如果列線GPIO口的數(shù)據(jù)等于零,表示第2 行當(dāng)前列有按鍵按下,所有行列對應(yīng)的GPIO口設(shè)置為高電平,程序跳出循環(huán)返回。按照上面規(guī)則遍歷所有行線的所有列線找出可能的按鍵位置,將鍵值返回給主程序,主程序根據(jù)鍵值執(zhí)行相應(yīng)的處理操作。
使用矩陣鍵盤時,在按鍵按下及松開瞬間觸點電壓跳變會引起現(xiàn)按鍵自身及按鍵之間的電壓抖動,造成按鍵誤判引起輸入錯誤,所以需要在按鍵識別程序中加入去抖處理,如圖4所示,可以采用延時二次判斷的方法消除按鍵抖動影響,在第1 次按照行列順序掃描法檢測到有按鍵按下后,采用程序定時延時,讓單片機(jī)空閑10ms 后,再次掃描鍵盤判斷鍵盤狀態(tài)。若2 次判斷都是同一按鍵,則確定并返回該按鍵值,否則清除按鍵判定狀態(tài),重新進(jìn)行按鍵判定。
圖4 行列掃描軟件去抖流程圖
使用軟件定時延時會浪費(fèi)單片機(jī)時間資源,如果單片機(jī)中斷資源豐富,可以給矩陣鍵盤輸入GPIO口設(shè)置中斷,減少延時造成的單片機(jī)時間占用;或者讓單片機(jī)運(yùn)行實時系統(tǒng),將按鍵掃描設(shè)計為系統(tǒng)任務(wù)也可減少單片機(jī)時間浪費(fèi)。
(2)問題及改進(jìn)
在快遞柜中使用塑料矩陣鍵盤實驗時,會出現(xiàn)小概率的錯誤輸入,分析原因發(fā)現(xiàn),塑料鍵盤按鍵時震動較大,會引起相近觸點的較長時間的電壓變化,造成按鍵誤判。比如“A”鍵按下時,引起“6”“9”按鍵觸點電壓變化,按照順序判決規(guī)則,“6”“9”鍵判定次序在“A”鍵之間,假設(shè)“6”“9”鍵電壓變化持續(xù)時間超過去除抖動的延時時長,這時就產(chǎn)生誤判。如果增加軟件延時時間,能減少誤判概率,但會造成輸入遲滯、影響用戶體驗。
改進(jìn)思路是,“6”“9”鍵的電壓變化由于按鍵“A”按下引起的,其電壓變化量和持續(xù)時間必然比按鍵“A”低,在一定時間內(nèi)進(jìn)行多次判定,并對多次按鍵判定值統(tǒng)計,計數(shù)最高且溢出門限的鍵值作為最終按鍵判定,這種方法找出真正的按鍵“A”概率最高,誤判最少。單片機(jī)主頻高,IO 輸出速度快,單次按鍵判定的時間可以做到很小,從而既提高了識別準(zhǔn)確度,又減少了輸入響應(yīng)時間。
基于統(tǒng)計溢出方法,根據(jù)STM32 單片機(jī)中斷、定時器資源優(yōu)化矩陣鍵盤識別去除抖動程序。
基于統(tǒng)計溢出的矩陣鍵盤按鍵識別程序流程如圖5所示,系統(tǒng)上電后,對STM32 單片機(jī)定時器、鍵盤GPIO、液晶屏GPIO 等設(shè)備進(jìn)行初始化設(shè)置后進(jìn)入主循環(huán),定時器產(chǎn)生中斷后,檢測矩陣鍵盤狀態(tài),統(tǒng)計按鍵值,主循環(huán)按鍵判斷程序根據(jù)按鍵統(tǒng)計值,做出按鍵判定,通過ST7920 液晶屏顯示鍵值并執(zhí)行相應(yīng)的操作。
圖5 基于統(tǒng)計溢出的矩陣鍵盤按鍵識別流程圖
系統(tǒng)軟件關(guān)鍵程序包括鍵盤初始化、定時器初始化、按鍵檢測等。
(1)矩陣鍵盤初始化程序
在key.c 文件中編寫矩陣鍵盤初始化程序。在KeyIO 結(jié)構(gòu)體數(shù)組中填寫8 組GPIO 引腳數(shù)據(jù){GPIO 引腳組和GPIO 引腳},前4 組對應(yīng)矩陣鍵盤行線,后4 組對應(yīng)矩陣鍵盤列線。
typedef struct{GPIO_TypeDef* GPIOX; unsigned int GPIO_Pin;} KEYIO[2][4];
KEYIO KeyIO= {{{IO1引腳組,組內(nèi)序號},{IO2引腳組,組內(nèi)序號},...,{IO8 引腳組,組內(nèi)序號}}};
使用枚舉數(shù)組定義存儲GPIO 引腳可以使引腳調(diào)整更簡單,可根據(jù)STM32 開發(fā)板引出的GPIO 進(jìn)行調(diào)整,引腳不需要在同一GPIO 引腳組,也不需要順序相鄰。
OverflowTimes = 50;
unsigned char Key_Times[17]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
Key_Times 數(shù)組用于存儲按鍵判定統(tǒng)計值,數(shù)組的1-16元素指對應(yīng)矩陣鍵盤的16個按鍵,數(shù)組17 元素對應(yīng)無輸入按鍵判定計數(shù),OverflowTimes 是統(tǒng)計溢出門限參數(shù),可根據(jù)屏幕響應(yīng)時間、系統(tǒng)負(fù)荷、實際使用體驗調(diào)整。
void KEYClock_Init(void){ RCC_APB2PeriphClock Cmd(RCC_APB2_GPIOX,ENABLE);}
KEYClock_Init()函數(shù)用于打開鍵盤GPIO 對應(yīng)的時鐘,RCC_APB2_GPIOX 要包括矩陣鍵盤所有GPIO 所在的引腳組。鍵盤GPIO 初始化函數(shù)KEY_Init()完成對矩陣鍵盤使用GPIO 初始化設(shè)置,其中4 條行線對應(yīng)GPIO 引腳設(shè)置為推挽輸出即GPIO_Mode_Out_PP,4 條列線對應(yīng)GPIO 引腳設(shè)置為上拉輸入即GPIO_Mode_IPU,GPIO 引腳速度均設(shè)置為50MHz 即GPIO_Speed_50MHz。
(2)定時器初始化及中斷處理程序
定時器初始化函數(shù)TIM4_Int_Init( )在timer.c文件中,使用TIM4 定時器,并設(shè)置中斷優(yōu)先級、時鐘分頻因子、定時量、計數(shù)模式、開啟定時器4 中斷。
定時器中斷處理TIM4_IRQHandler( )函數(shù)如下所示,在TIM4 中斷中完成軟件看門狗設(shè)置、息屏計數(shù)、系統(tǒng)狀態(tài)標(biāo)志設(shè)置等。
void TIM4_IRQHandler(void) {
if (TIM_GetITStatus(TIM4, TIM_IT_Update) !=RESET) {
TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //定時器像清除標(biāo)志位
IWDG_Feed();//軟件看門狗設(shè)置
Idle_Time++;//息屏計數(shù)器KEY_Scan_Timer();
if(Idle_Time>1800){
global_state=0;
Idle_Time=0;
Idle_Run=0; } } }
基于定時器的矩陣鍵盤掃描判定統(tǒng)計KEY_Scan_Timer(void)函數(shù)如下所示,依次將行線設(shè)置為高電平,判斷可能的按鍵并計數(shù)統(tǒng)計。
void KEY_Scan_Timer(void){
unsigned char i,j,k;
extern unsigned char Key_Times[16];for(j = 0; j<4; j++){
Key_Times[16]++;//默認(rèn)無輸入,則Key_Times[16]加1
for(k = 0; k<4; k++) {
if(GPIO_ReadInputDataBit(KeyIO[1][k].GPIOX,KeyIO[1][k].GPIO_Pin)== 0){
Key_Times[j*4+k]++;//檢測列 列值為 i
Key_Times[16]--;} }//有按鍵則Key_Times[16]減1 GPIO_SetBits(KeyIO[0][j].GPIOX,KeyIO[0][j].GPIO_Pin); } }
(3)基于統(tǒng)計溢出的單鍵、長按鍵識別程序
找出判定次數(shù)最多的鍵值,如果該鍵統(tǒng)計值大于溢出門限,則最終判定本次輸入有效鍵值為該按鍵,如果本次有效按鍵和上一次按鍵相同,則RepeatKeyTimes 加1。在主程序循環(huán)中做長按鍵處理,如果本次有效按鍵和上一次按鍵相同3 次以上,則判定為長按鍵,執(zhí)行長按鍵并將RepeatKeyTimes 置零。
for(i = 0; i<17; i++){
課程目標(biāo)是體現(xiàn)課程理念、展現(xiàn)課程價值追求的核心部分,在經(jīng)歷活動實施過程中應(yīng)以幼兒的成長為核心,關(guān)注幼兒的體驗、情感、態(tài)度和綜合能力的發(fā)展,制定經(jīng)歷活動的總目標(biāo)。為了使活動目標(biāo)具有更強(qiáng)的指向性和導(dǎo)向性,使教師在具體的實施過程中能更準(zhǔn)確地把握教育目標(biāo),可對總目標(biāo)進(jìn)行分解和細(xì)化,同時,在設(shè)置經(jīng)歷活動總目標(biāo)的基礎(chǔ)上,針對大、中、小班幼兒的年齡特點、認(rèn)知水平、實踐能力,制定各個不同年齡段的具體目標(biāo),并在此基礎(chǔ)上確立各個經(jīng)歷活動目標(biāo)。利用三級目標(biāo)體系使經(jīng)歷活動目標(biāo)層次化,且不同層次目標(biāo)間具有一致性和聯(lián)系性,為教師的實踐操作提供落腳點和正確方向。
if( Key_Times[i]>FirstKeyTimes){
FirstKeyTimes=Key_Times[i];
FirstKeyNumber=i; }
if(FirstKeyTimes > OverflowTimes) {
if(FirstKeyNumber==LastKeyValue){
RepeatKeyTimes++; //長按判斷
}else{ RepeatKeyTimes=0; }
for(j = 0; j<17; j++){
Key_Times[j]=0;}LastKeyValue =FirstKeyNumber; } }
(4)基于統(tǒng)計溢出的組合鍵識別程序
找出判定次數(shù)前2 名的鍵值,如果排名第2的判定統(tǒng)計值大于溢出門限,且長時間按下,則最終判定本次輸入有效鍵值為雙鍵組合。
for(i = 0; i<17; i++){
if( Key_Times[i]>=FirstKeyTimes) {
SecondKeyTimes=FirstKeyTimes;
SecondKeyNumber=FirstKeyNumber;
FirstKeyTimes=Key_Times[i];
FirstKeyNumber=i; }
if( SecondKeyTimes > OverflowTimes){/*執(zhí)行雙鍵組合特殊操作*/ }
else if(FirstKeyTimes > OverflowTimes){
if(FirstKeyNumber==LastKeyValue){
RepeatKeyTimes++; } //長按
else { RepeatKeyTimes=0; }
for(j = 0; j<17; j++){
Key_Times[j]=0;}
LastKeyValue =FirstKeyNumber; } }
如圖6所示,在使用改進(jìn)后的基于統(tǒng)計溢出的矩陣鍵盤按鍵識別程序后,快遞柜按鍵輸入流暢度明顯提升,得到較好的使用體驗評價。
圖6 快遞柜產(chǎn)品應(yīng)用
本文針對行列掃描延時去抖法進(jìn)行矩陣鍵盤按鍵識別時存在的按鍵誤判問題,使用基于統(tǒng)計溢出的按鍵識別方法改進(jìn)程序設(shè)計,提高按鍵識別準(zhǔn)確率,降低按鍵誤判概率。在快遞柜產(chǎn)品的實際應(yīng)用中,鍵盤輸入流暢度提升,用戶使用體驗得到改善。