- AVR单片机很简单:C语言快速入门及开发实例
- 曹振华主编
- 2169字
- 2020-08-28 00:36:28
2.8 I/O口键盘扫描电路应用实例
2.8.1 薄膜键盘基础知识
薄膜键盘是薄膜开关范畴的一例,按键较多且排列整齐有序的薄膜开关,人们习惯称之为“薄膜键盘”,薄膜键盘的实物如图2-26所示。薄膜键盘是近年来国际流行的一种集装饰性与功能性为一体的一个操作系统。
图2-26 薄膜键盘实物图
薄膜键盘由面板层、面胶层、控制电路上层和下层、夹胶层、背面胶层组成。
(1)面板层 面板层一般在低于0.25mm的PET、PC等无色透光片材丝印上精美图案和文字制作而成,因面板层最主要起标识和按键作用,所以选用材料必须具有高透明度、高油墨附着力、高弹性、高韧性等特点。
(2)面胶层 面胶最主要的作用是将面板层与电路层紧密相连,以达到密封和连接的效果,此层一般要求厚度在0.05~0.15mm之间,具有高强的黏性和防老化性;在生产中,一般选用专用的薄膜开关双面胶,有些薄膜开关要求能防水防高温,因此面胶也必须根据需要而使用不同性质的材料。
(3)控制电路上层和下层 此层均采用性能良好的聚酯薄膜(PET)作为开关电路图形的载体并在其上用特殊的工艺丝印上导电银浆和导电碳浆,使其具有导电性能,其厚度一般在0.05~0.175mm以内,最常见的是用0.125mm PET。
(4)夹胶层 它处于上电路与下电路层之间并起密封和连接的作用,一般采用PET双面胶,其厚度有0.05~0.2mm不等;在选择此层材质的时候应充分考虑产品的整体厚度、绝缘性、电路按键包手感和密封性。
(5)背胶层 背胶的采用与薄膜开关与何种材质相粘贴紧密相关,比较常采用的有普通双面胶、3M胶、防水胶等。
2.8.2 单片机识别键盘按键
为了识别键盘上的闭合键,常用的键码识别方法有行扫描法、行反转法及行列扫描法等。
(1)行扫描法 行扫描法识别按键的基本原理是:先将所有的行线置0,读列线的值,若此时列线上的值全为1,说明无键按下。若有某位为0,则说明对应这一列上有键按下,这时改变行扫描码,使行线逐行为0,依次扫描。当读到某一列线的值为0时,就可根据此时的行扫描码和列线的值唯一地确定按键的位置,同时也就确定了该键的扫描码。
(2)行反转法 行反转法也是识别按键的常用方法,它的基本原理是:将行线接一个数据端口,让它先工作在输出方式:将列线也接到一个数据端口,让它先工作在输入方式。程序使CPU通过输出端口往各行线上全部送低电平,然后读入列线值。如果此时有某键被按下,则必定会使某列线值为0。接着,程序再对两个端口进行方式设置,使接行线的端口改为输入方式,接列线的端口改为输出方式。并且,将刚才读得的列值从列线所接端口输出,再读取行线的输入值。那么,闭合键所在的行线值必定为0。这样,当一个键被按下时,必定可以读得一对唯一的行值和列值。与之配合,行、列线所接的数据端口应能够改变输入、输出方式。
(3)行列扫描法 该方法基本思路为:通过计数译码,依次将各行输出为0,其余作为1。在扫描每一行时,读列线若全为1,说明此行无键按下:若某一列为0,说明有键按下,且行号和列号已经确定。然后用同样的办法,依次向列线扫描输出,读行线。如果两次所得的行号和列号分别相同,则确定了闭合键的键码。
本节将采用扫描速度比较快的反转法为例进行编程,使大家掌握I/O端口的基本操作并了解反转法的编程方法。
控制电路的键盘为4行4列的矩阵式键盘。判键过程中,首先置列端口为输出,行端口为输入,并令列输出全部为0。读取行端口,若有端口为0,表示有按键按下。延时一定时间后,仍读取行端口,若仍有端口为0,表明确实有按键按下,而不是干扰造成的,此时记录行号row1并进行列的判断。在列判断过程中,首先置行端口为输出,列端口为输入,并令行输出全0,读取列端口记录列号coll,按键编号Key_num=(row1-l)*4+coll,键盘判断流程如图2-27所示。
图2-27 键盘判断流程图
2.8.3 硬件电路设计
键盘设计采用了4行4列的矩阵式键盘,键盘8个引脚分别通过510Ω的限流电阻与单片机的I/O端口相连,由于设计较复杂系统时,往往会优先考虑ATmega128单片机自身的片上资源和外设接口,键盘所用的I/O端口一般会最后根据系统所占I/O端口的情况进行分配,考虑到键盘扫描程序的普遍性,本章设计的键盘扫描硬件电路采用了不连续的I/O端口,ATmega128键盘扫描硬件电路如图2-28所示。4×4位薄膜键盘实物图和原理图如图2-29所示。
图2-28 ATmega128键盘扫描硬件电路
图2-29 4×4位薄膜键盘实物图和原理图
2.8.4 程序设计
键盘扫描采用线反转法,首先将列线PF0~PF3编程为输出线,行线PE3、PB0、PC0、PC1编程为输入线,使列输出全部为零电平,则行线中电平由高变低的即为按键所在的行;然后将列线PF0~PF3编程为输入线,行线PE3、PB0、PC0、PC1编程为输出线,使行输出全为零电平,则列线中电平由高变低的即为按键所在的列;这样便可确定键值。在键值扫描子程序中通过软件延时10ms,是为了消除按键所带来的抖动,以避免产生误判。并在程序的最后将不连续的行线PE3、PB0、PC0、PC1进行标准化处理,完成按键码值计算。
程序清单如下:
uint8_t keyboard_acan(void) { //变量定义 uint8_t temp,row1,coll,row2,co12; uint8_t temp1,temp2,temp3,temp4; unsigned int i,j; //行列初始化 rowl= 0; coll= 0; row2= 0; col2= 0; //端口初始化 DDRF1= 0x0F; //设置列PF0~PF3为输出,行PE3、PB0、PC0、PC1为输入 cbi(DDRE,3); cbi(DDRB,0); cbi(DDRC,0); cbi(DDRC,1); sbi(PORTE,3); sbi(PORTB,0); sbi(PORTC,0); sbi(PORTC,1); PORTF&= 0xF0; //列输出全 0 //扫描开始 //扫描行 for(;;) { temp1= PINE; temp1&= 0x08; temp2= PINB; temp2&= 0x01; temp3= PINC; temp3&= 0x01; temp4= PINC; temp4&= 0x02; if(1(temp1&&temp2&&temp3&&temp4) break; } for (i= 1;i< < 0xfff0;i+ + ) { for(j= 0;j< 3;j+ + ) (;) } temp1= PINE; temp&= 0x08; temp1&= 0x08; temp2= PINB; temp2&= 0x01; temp3= PINC; temp3&= 0x01; temp4= PINC; temp4&= 0x02; if(1(temp1&&temp2&&temp3&&temp4) { for(;;) { temp1= PINE; temp&= 0x08; temp1&= 0x08; temp2= PINB; temp2&= 0x01; temp3= PINC; temp3&= 0x01; temp4= PINC; temp4&= 0x02; if(temp1= = 0) { row1= 1; } if(temp2= = 0) { row1= 2; } if(temp3= = 0) { row1= 3; } if(temp4= = 0) { row1= 4; } if((row1< 5)&(row1> 0)) { break; } } while(coll= = 0) { temp= 0xFF; DDRB1= 0xF0; //设置行PB4~PB7为输出,列PD4~PD7为输入 DDRD&= 0x0F; PORTD1= 0xF0; //上拉电阻使能 PORTB&= 0x0F; //行输出全 0 DDRF&= 0xF0; //设置列PF0~PF3为输入,行PB3、PB0、PC0、PC为输出 sbi(DDRE,3); sbi(DDRB,0); sbi(DDRC,0); sbi(DDRC,1); cbi(PORTE,3); cbi(PORTB,0); cbi(PORTC,0); cbi(PORTC,1); PORTF1= 0x0F; //上拉电阻使能 temp= PINF; temp&= 0x0F; switch (temp) { case 0x0E; coll= 1; break;跳出 switch case 0x00; coll= 2; break; case 0xB; coll= 3 break; case 0x07; coll= 4; break; default; break; } } temp= 4*(row1- 1); temp+ = coll; return temp; } }