单片机之键盘工作原理
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
理想波形
实际波形
按下抖动
稳定闭合
释放抖动
软件消抖方法:当判别到键盘上有键闭合后,延时一段时间再 判别键盘的状态,若仍有键闭合,则认为键盘 上有一个键处于稳定的闭合状态,否则认为键 抖动。
键盘有两种结构:独立式按键和矩阵式按键。 1.独立式按键
独立式键盘中每个按键都单独连接到单片机的一个 I/O端口引脚上。
实例
独立按键识别
【要求】采用独立按键方式实现下述功能:开机时LED全熄, 然后根据按键动作使相应灯亮,并将亮灯保持到按压其它键 时为止。
做输入, 先写1
【分析】
① 按键的闭合电平为0, 但LED 的驱动电平为1,故不能直接将 P0口的状态送到P2口,而应使 其先取反再送出; ② 使按键按下LED点亮,松开 时保持不变。
#include<reg51.h> void delay(unsigned int z) { unsigned int x,y; for(x=z;x>0;x--) for(y=125;y>0;y--); } void main() { unsigned char key; P2=0x00; P0=0x0f; while(1) { key=P0; if(key!=0x0f) { delay(10); if(key!=0x0f) P2=~key; } } }
实例 运行效果
Unsigned char key_val[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d, 0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77}
利用循环变量i控制比对过程,两者相等时的i就是闭合键的键值。
for(i=0;i<16;i++) { if(key_val[i]==P3) return i; }
①判断是否有键压下 写P3端口0xf0(行线电平=0,列线电平=1) 读P3端口:若P3 = 0xf0→无按键压下,不必后续判断; 若P3 ≠0xf0 →有键压下
②去除键的机械抖动 其方法为:当判别到键盘上有键闭合后,延时一段时 间再判别键盘的状态,若仍有键闭合,则认为键盘上有一 个键处于稳定的闭合状态,否则认为键抖动。
③判别闭合键的键值 其方法为:对键盘的行线进行扫描,P3口依次循环输 出0xfe、0xfd、0xfb和0xf7,相应地读P3口,若高4位 P3.7~P3.4全为“1”,则说明该行上没有键闭合;否则, 这一行上有键闭合,而且就是行线为0,列线为0的交叉键。 高4位和低四位合并即得到键模。
键模——按键压下时形成的电平编码值 键值——按键的人为定义值
当按键未按下压时,Px.n端口为高电平;按压按键后为 低电平。
按键在闭合和断开时,触点会存在抖动现象:
+5V
无抖动
理想波形 A 实际波形
按下抖动
B 稳定闭合
释放抖动
+5V
有抖动
图为键闭合时列线电压波形。键闭合和断开过程中存在抖 动期(呈现一串负脉冲),抖动时间长短与开关的机械特性有关, 一般为5~10 ms之间;稳定闭合期由操作员的按键动作所确定, 一般为数百毫秒到几秒。为了保证CPU对键的闭合做一次处理, 必须去除抖动,在键的稳定闭合或断开时,读键的状态。
第一行的键模: 11101110、11011110、 10111110、01111110 整个4x4键盘的键模: 0xee、0xde、0xbe、0x7e 0xed、0xdd、0xbd、0x7d 0xeb、0xdb、0xbb、0x7b 0xe7、0xd7、0xb7、0x77
④ 形成压下键的键模
将各键的键模依次存放在一个数组中,其顺序号就是键值。
10kΩ
10kΩ
10kΩ
10kΩ
和列线连接的单片机端 口,作为输入
当键盘上没有键闭合时,所有的行线和列线断开,列线都 呈高电平。当键盘上某一个键闭合时,则该键所对应的列线与行 线短路。此时列线的电平由相应的行线的电位所决定。
键盘扫描原理(以P3口接4×4键盘为例)
键盘扫描原理(以P3口接4×4键盘为例)
行列式键盘的特点:占用IO口线少,但软件过程复杂。
实例 行列式键盘 要求按下任意按键后,数码管上显示该键的键值(0~F)
参考程序
#include<reg51.h> unsigned char duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71}; unsigned char key_val[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb, 0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77}; unsigned char key_scan[]={0xfe,0xfd,0xfb,0xf7}; void delay(unsigned int z) { unsigned int x,y; for(x=z;x>0;x--) for(y=125;y>0;y--); } void main() { unsigned char i,j; P2=0; while(1) { P3=0xf0; if(P3!=0xf0) { delay(10); if(P3!=0xf0) } } } } for(i=0;i<4;i++) { P3=key_scan[i]; for(j=0;j<16;j++ if(key_val[j]==P3) P2=duan[j];
键值: 按压K1——xxxx xx10(0x02) 按压K2——xxxx xx01(0x01) 无按键——0000 xx11(0x03)
则由得到的键值对应确定dun、dir的值,用switch语句实现。
temp=P0&0x03; switch(temp) { case 0x02:run=1; dir=1; break; case 0x01:dir=0;break; }
LED循环流程
亮灯P2输出:
xxxx xxxx xxxx xxxx
0001 0010 0100 1000
LED状态码数组[]ຫໍສະໝຸດ Baidu= {0x01,0x02,0x04,0x08}
分析——搞清全部逻辑关系
总体关系(主函数)流程
(键值函数)
参考程序:
#include<reg51.h> unsigned char led[]={0x01,0x02,0x04,0x08}; // 从上到下的流水灯 bit run,dir; unsigned char temp,i; void delay(unsigned int z) { unsigned int x,y; for(x=z;x>0;x--) for(y=125;y>0;y--); }
参考程序
运行 效果
2、 行列式键盘原理与编程 独立式键盘的电路简单,易于编程,但占用的IO口线较多, 当需要较多按键时可能产生IO资源紧张问题。
独立式键盘
行列式键盘——将IO口分为行线和列线,按键跨接在行线 和列线上,列线通过上拉电阻接正电源。
+5V
和行线连接的单片机 端口,作为输出
P1.0 89S51 P1.1 P1.2 P1.3 P1.4 P1.5 P1.6 P1.7
if(run==1) { if(dir==1) for(i=0;i<=3;i++) { P2=led[i]; delay(200); } else for(i=4;i>=1;i--) { P2=led[i-1]; delay(200); } } else P2=0; } }
void main() { while(1) { temp=P0&0x03; switch(temp) { case 0x02: run=1;dir=1; //启动,自 上往下 break; case 0x01:dir=0; //自下往上 break; }
键盘工作原理
1. 按键输入的特点 键盘实质上是一组按键开关的组合。通常使用的是触 点式的机械弹性开关。利用机械触点的通断,实现按下 时开关导通,释放时开关断开的功能。 按键触点的一端和单片机的I/O端口引脚连接,另 一端与电压信号相连,触点的通断即可引起端口引脚上 的电压变化,单片机通过程序读入I/O端口引脚电平信 号便可判断按键的状态。如下图所示。
特点是电路简单,但占用I/O口线较多。
例:按下按键,对应的LED灯亮
#include<reg51.h> void delay(unsigned int z) { unsigned int x,y; for(x=z;x>0;x--) for(y=125;y>0;y--); } void main() { unsigned char key; P2=0x00; P0=0x01; while(1) { key=P0; if(key!=0x01) { delay(10); if(key!=0x01) P2=~key; } } }
独立按键+数码管综合
实例 采用共阴极的数码管 实现功能要求:当按键按下时显示“ L2”,松开时显示 “H3”
算出L2H3的段码分别为: 0x38,0x5b,0x76,0x4f 位选信号构成位码: 0xfe,0xfd
void main() { #include<reg52.h> uchar i; #define uint unsigned int while(1) #define uchar unsigned char uchar duan[]={0x38,0x5b,0x76,0x4f}; //共 { 阴"L2H3" if(button==0) uchar wei[]={0xfe,0xfd}; delay(10); sbit button=P1^6; if(button==0) for(i=0;i<2;i++) void delay(uint z) { { P3=wei[i]; uint x,y; P2=duan[i]; for(x=z;x>0;x--) delay(10); for(y=125;y>0;y--); } } else for(i=0;i<2;i++) { P3=wei[i]; P2=duan[i+2]; delay(10); } } }
实例
键控流水灯
【要求】 K1为“启动键”,按压K1可产生“自下向上” 的流水灯运动; K2 为“方向键”,按压K2可产生“自下向上”运动。
启动 (=1) run 停止 (=0) ↓ dir ↑ (=0) (=1)
获取按下键值(键值函数)流程
按键动作判断——(P0 & 0x03)是否等于 0x03 若是,则无按键动作,反之则有按键动作