基于51单片机开发之键盘

发布者:幸福满溢最新更新时间:2015-02-09 来源: 51hei关键字:51单片机  键盘 手机看文章 扫描二维码
随时随地手机看文章
1、键盘分类
键盘分编码键盘和非编码键盘,键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码或键值的称为编码键盘,如计算机键盘。
  • 而靠软件编程来识别的称为非编码键盘;
  • 在单片机组成的各种系统中,用的最多的是非编码键盘。也有用到编码键盘的。
  • 非编码键盘又分为:独立键盘和行列式(又称为矩阵式)键盘。
    此图为矩阵键盘


此图为独立键盘
  • 在单片机内部P1,P2,P3口各I/O口线片内均有固定的上拉电阻,当这3个准双向I/O口作为输入口使用时,向该口先写“1” 才能读取这个I/O的状态,P3.4 =1 ,如果这个I/O口没有3态就是没有3态关系这个I/O就跟连接的元器件是一个线与的关系,所以按键按下去就是低电平。如果有3态的I/O口就是跟连接的器件是一个线或的关系,高阻态并非是高电平还是低电平,而是高阻状态,如果外接高它就是高,接低它就是低电平。
  • 实例:先写个程序检测下吧[page]
note:说明下这个程序就是每按下按键让一个数码管变一下,从0--9 然后再按变成0循环
#include
#define uchar unsigned char
sbit d1= P1^0; //这个脚接的是发光二极管。
sbit key1= P3^4 ;//接的一个按键
sbit dula = P2^6;// 段啦 控制数码管
sbit wela = P^7;// 位啦 控制数码管
uchar num;

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0};//编码表 数组 code 是在ROM区
void main(){
wela =1;
P0= Oxfe;
wela=0; //位选就打开一个数码管的

P3 = 0XFF; //把P3都给写1
while(1){ //轮循的方式
if(0==key1){
d1= 0; //点亮灯
num ++;//每按一次按键让num++
if (10==num)
num=0; //一个数码管就只能显示9

}else {
d1 = 1; //熄灭灯
}
dula =1;
P0 = table[num];
dula =0;
}

以上程序存在问题:按下按键时候数码管显示的不是1 2.....9 0 1... 原因是:你按下的大概低电平持续了20毫秒,20毫秒此程序执行了多少次了,所以数码管显示的不是1 可能是5 可能是8 9 。所以必须做一个松手检测。
#include
#define uchar unsigned char
sbit d1= P1^0; //这个脚接的是发光二极管。
sbit key1= P3^4 ;//接的一个按键
sbit dula = P2^6;// 段啦 控制数码管
sbit wela = P^7;// 位啦 控制数码管
uchar num;

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0};//编码表 数组 code 是在ROM区
void main(){
wela =1;
P0= Oxfe;
wela=0; //位选就打开一个数码管的

P3 = 0XFF; //把P3都给写1
while(1){ //轮循的方式
if(0==key1){
d1= 0; //点亮灯
num ++;//每按一次按键让num++
if (10==num)
num=0; //一个数码管就只能显示9
while (!key1) //松手检测 只要你按键按下去是0 取反 一直等待 否则跳出去到下面
}else {
d1 = 1; //熄灭灯

}
dula =1;
P0 = table[num];
dula =0;
}
以上程序虽然得到改善,但是存在按一下会加得不是1现象,当然几率不大,但确实存在。
  • 按键在闭合和断开时,触点会存在抖动现象



从这个图看按下和松开有毛刺 这个是硬件消抖动不要理解[page]
我们解决的是按下去的毛刺去掉:延时函数 10毫秒 也就是说我们第一次按下去的时候我们延时个10毫秒,实际上毛刺抖动为5毫秒左右,我们给10毫秒更稳定。程序如下:

#include
#define uchar unsigned char
sbit d1= P1^0; //这个脚接的是发光二极管。
sbit key1= P3^4 ;//接的一个按键
sbit dula = P2^6;// 段啦 控制数码管
sbit wela = P^7;// 位啦 控制数码管
uchar num;

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0};//编码表 数组 code 是在ROM区
//此为延时 测试值为1毫秒级
void delay(uint z)
{
uint t1,y;
for(t1=z;t1>0;t1--)
for(y=110;y>0;y--);
}

void main(){
wela =1;
P0= Oxfe;
wela=0; //位选就打开一个数码管的

P3 = 0XFF; //把P3都给写1
while(1){ //轮循的方式
if(0==key1){
delay(10);//延时10毫秒
if (0==key1){ //再确认下确实按下去了多了delay 和if 判断
d1= 0; //点亮灯
num ++;//每按一次按键让num++
if (10==num)
num=0; //一个数码管就只能显示9
}
while (!key1) //松手检测 只要你按键按下去是0 取反 一直等待 否则跳出去到下面
}else {
d1 = 1; //熄灭灯

}
dula =1;
P0 = table[num];
dula =0;
}
经过以上的更改是改善了问题但是还是会存在抖动现象,原因是我们只是在按下去消除抖动,没有在松手消除抖动,但是实际的项目中一般我们都是按下去的时候做消除抖动,如果想要达到更好的效果可以在松手也做消除抖动。程序简单修改如下:
#include
#define uchar unsigned char
sbit d1= P1^0; //这个脚接的是发光二极管。
sbit key1= P3^4 ;//接的一个按键
sbit dula = P2^6;// 段啦 控制数码管
sbit wela = P^7;// 位啦 控制数码管
uchar num;

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0};//编码表 数组 code 是在ROM区
//此为延时 测试值为1毫秒级
void delay(uint z)
{
uint t1,y;
for(t1=z;t1>0;t1--)
for(y=110;y>0;y--);
}

void main(){
wela =1;
P0= Oxfe;
wela=0; //位选就打开一个数码管的

P3 = 0XFF; //把P3都给写1
while(1){ //轮循的方式
if(0==key1){
delay(10);//延时10毫秒
if (0==key1){ //再确认下确实按下去了多了delay 和if 判断
d1= 0; //点亮灯
num ++;//每按一次按键让num++
if (10==num)
num=0; //一个数码管就只能显示9
}
while (!key1) //松手检测 只要你按键按下去是0 取反 一直等待 否则跳出去到下面
dely(10); //松手消除抖动 就是延时
while(!key1);// 再确认下 然后执行下面语句

}else {
d1 = 1; //熄灭灯

}
dula =1;
P0 = table[num];
dula =0;
}

以上程序是独立键盘的应用中确实存在的一些问题和本人的一些简单的解决问题的思路。当然延时也可以改成5毫秒尽量的不要让MCU过多的等待。一般的项目中都不会采用延时来去抖动,可以用定时器来去除抖动。特别在一些嵌入式系统中常用定时器去抖动,因为嵌入式设备的硬件资源太宝贵了哦。希望大牛们给个定时器的去除抖动程序。!!!!
关键字:51单片机  键盘 引用地址:基于51单片机开发之键盘

上一篇:基于51单片机的D/A & A/D 与单片机接口原理
下一篇:51单片机数码管交通灯程序

推荐阅读最新更新时间:2024-03-16 13:53

51 单片机串行通讯中波特率的自动检测
本文介绍一种在 80C51 串行通讯应用中自动检测波特率的方法。按照经验,程序起动后所接收到的第1个字符用于测量波特率。 这种方法可以不用设定难于记忆的开关,还可以免去在有关应用中使用多种不同波特率的烦恼。人们可以设想:一种可靠地实现自动波特检测的方法是可能的,它无须严格限制可被确认的字符。问题是:在各种的条件下,如何可以在大量允许出现的字符中找出波特率的定时间隔。 显然,最快捷的方法是检测一个单独位时间(single bit time),以确定接收波特率应该是多少。可是,在 RS-232 模式下,许多 ASCII 字符并不能测量出一个单独位时间。对于大多数字符来说,只要波特率存在合理波动(这里的波特率是指标准波特率)
[单片机]
51 单片机串行通讯中波特率的自动检测
51单片机产品数量自动计量系统Proteus仿真程序设计
1. 设计要求 如右图所示,以MCS-51系列单片机为核心设计一个具有独创功能的计量控制系统,控制瓶装产品包装生产流水线,每计满一定瓶数产品时发出一个包装控制信号,通过相关电路驱动包装机完成一次包装动作。 要求: 1. 每箱产品的瓶数为51瓶,可记录已封装箱数; 2. 系统具有人机交互功能,可由用户控制流水线工作速度,并实时显示已计量瓶数和封装箱数; 3. 流水线使用48V 2000W直流电机进行传动,设计MCU与该电机的接口电路,实现流水线传动的启停和速度 控制,并仿真其可行性; 4. 设计用于检测瓶子的 传感器应用电路,实现对瓶数的感测; 5. 包装机数据接口为 RS-485接口,设计MCU与包装机的接口电路; 6.
[单片机]
<font color='red'>51单片机</font>产品数量自动计量系统Proteus仿真程序设计
51单片机软件用定时器模拟串口程序
模拟串口用定时器完成,每一个串口要占用一个定时器,发送很好办,每次定时器中断(1BIT的时间)传送一个Bit,接收就要你好好处理了,这个我模拟的一个串口,用的W77E58,实际工作时只用到了半双工。 //使用硬件:定时器0,定时器0中断,定时器1中断,外中断5 //波特率 9600 4800 2400 1200 600 300 //每BIT周期数 96 96*2 96*4 96*8 96*16 96*32 //以96为单位不同的波特率选用不同的倍率 //如果对方在每位的1/2处采样,则发送中断的响应时间最多是48个时钟周期 //也许可以置发送中断以较高的优先级来解决,实验表明发送可以工作于9600 //但若有其它中断,并且
[单片机]
Proteus仿真51单片机C语言程序实例-开关控制报警器
简介:51单片机C语言程序实例-开关控制报警器(用K1开关控制报警器,程序控制P1.0输出两种不同频率的声音,模拟很逼真的报警效果)。
[单片机]
Proteus仿真<font color='red'>51单片机</font>C语言程序实例-开关控制报警器
单片机第一步——51单片机
俗话说:“天才第一步,XX纸尿裤。”哈哈!扯远了。不过,我们今天说的,确实可能是绝大多数嵌入式工程师或者电子爱好者接触的第一款单片机——51单片机。 图为51单片机驱动LED点阵的电子制作 51单片机只是爱好者们的一种“爱称”,51单片机指的是所有搭载可执行INTEL 8031指令系统的MCU的单片机。这里,我们需要澄清单片机实际使用方面的一个产品概念,MCS-51单片机是美国INTEL 公司于1980年推出的产品,典型产品有 8031(内部没有 程序存储器 ,实际使用方面已经被市场淘汰)、8051(芯片采用HMOS,功耗是630mW,是89C51的5倍,实际使用方面已经被市场淘汰)和8751等通用产品,一直到现在, M
[单片机]
单片机第一步——<font color='red'>51单片机</font>
51单片机的酒精检测Proteus仿真+源代码
酒精传感器仿真中没有,其实就是传感器检测时相应的电阻值会变化,用滑动电位器代替就ok 仿真原理图如下 单片机源程序如下: //程序头函数 #include reg52.h //显示函数 #include display.h #include intrins.h #include eeprom52.h #include temp.h //宏定义 #define uint unsigned int #define uchar unsigned char #define Data_ADC0809 P1 //管脚声明 sbit P34=P3^4;//温度 sbit LED_R= P2^2; //红指示灯 sbit LE
[单片机]
<font color='red'>51单片机</font>的酒精检测Proteus仿真+源代码
基于51单片机、串口通信、ASP.NET的密码锁系统
实现的功能:密码锁,红外控制,温度计功能等 连线:键盘接P0,P2接数码管,接上LCD,P1.0接蜂鸣器,P1.2-P1.7接步进电机 C程序: #include reg52.h #include intrins.h typedef unsigned int uint; typedef unsigned char uchar; bit FlagC=1; //接受和发送的标志位 sbit P10=P1^0; //控制蜂鸣器响 sbit IRIN = P3^2; //红外接收器数据线 uchar IRCOM ; uint nn=11;//用来判断红外发送的信号是数字几 //////温度液晶/////////////
[单片机]
基于USB总线和89C51单片机的数据采集系统设计
在工业生产和科学技术研究过程的各行业中,常常要对各种数据进行采集,现在常用的采集方式是在PC机或工控机内安装数据采集卡,如A/D卡及RS-422卡、RS-485卡。采集卡不仅安装麻烦,易受机箱内环境的影响,而且由于受计算机插槽数量和地址、中断资源的限制,不可能挂接很多设备。而通用串行总线(Universal Serial Bus,简称USB)的出现能很好地解决以上这些冲突。我们利用89C51单片机设计了基于USB总线的数据采集设备,并可与MAX485结合起来实现数据的远程采集。 系统硬件设计 USB数据采集系统硬件模块主要由串行A/D转换器、89C51芯片、USB接口芯片和多路模拟开关等组成。硬件总体结构框图如图1所示。
[应用]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved