学习目标:
1.原理图
2.程序代码
3.键值检测与显示
4.按键消抖
5.完整的按键检测
6.矩阵键盘
学习内容:
1)原理图
2)程序代码(监测按键少,可以采用位监测,多需要采用端口字节变量监测)
#include <reg51.h>
//当前要处理的是K1,对应P1.0 I/O口,操控的LED是LED1,对应P0.0
sbit key1 = P1^0;
sbit led1 = P0^0;
void delay(void)
{
unsigned char i,j;
for(i=0;i<100;i++)
for(j=0;j<100;j++);
}
void main()
{
while(1)
{
//读key1引脚
if(key1==1)
{
//没有按键
led1=0; // led1熄灭
}
else
{
//有按键
led1=1; // led1点亮
}
delay();
}
}
3)键值检测与显示
键值
( 1 ) 一般的产品中按键都有很多, 对于整个程序来说一般都是把按键进行编码, 给每个按键一个对应的编码值, 就叫做按键的键值。
( 2 ) 在正式的比较庞大的程序中, 按键的检测部分和处理部分都是隔开的。这两部分隔开有利于各自部分的程序编写, 两部分之间用键值来连接。按键监测部分负责监测按键, 一旦发生一个按键事件就产生一个键值, 然后将键值传递给按键处理部分。
加入数码管显示键值
( 1 ) 整个程序包括2 部分: 1 部分做按键监测并且发出键值, 另一部分负责将接收到的键值显示在独立数码管上。
#include <reg51.h>
//当前要处理的是K1,对应P1.0 I/O口,操控的LED是LED1,对应P0.0
sbit key1 = P1^0;
sbit led1 = P0^0;
//独立数码管的段码表
unsigned char val[16] = {0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
void delay(void)
{
unsigned char i,j;
for(i=0;i<100;i++)
for(j=0;j<100;j++);
}
//数码管显示
void display(unsigned char num)
{
P0 = val[num];
}
void main()
{
unsigned char keynum = 0;
char i=0;
while(1)
{
unsigned char i = 0;
for(i=0; i<8; i++)
{
if((P1 & (0x1<<i))) == 0
{
keynum = i+1;
}
}
// if(P1 == 0xfe)
// {
// keynum = 1;
// }
// if(key2 == 0)
// {
// keynum = 2;
// }
// if(key3 == 0)
// {
// keynum = 3;
// }
// if(key4 == 0)
// {
// keynum = 4;
// }
// if(key5 == 0)
// {
// keynum = 5;
// }
// if(key6 == 0)
// {
// keynum = 6;
// }
// if(key7 == 0)
// {
// keynum = 7;
// }
// if(key8 == 0)
// {
// keynum = 8;
// }
delay();
display(keynum);
}
}
4)按键消抖
#include <reg51.h>
//当前要处理的是K1,对应P1.0 I/O口,操控的LED是LED1,对应P0.0
sbit key1 = P1^0;
sbit led1 = P0^0;
unsigned char dnum=0;
//独立数码管的段码表
unsigned char val[16] = {0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
void delay(void)
{
unsigned char i,j;
for(i=0;i<100;i++)
for(j=0;j<100;j++);
}
//数码管显示
void AddDisplay()
{
dnum = dnum+1;
if(dnum>15)
{
dnum = 0;
}
P0 = val[dnum];
}
void main()
{
unsigned char keynum = 0;
char i=0;
while(1)
{
unsigned char i = 0;
if(key1 == 0)
{
delay();
if(key1==0)
{
AddDisplay();
}
}
delay();
}
}
5)完整的按键检测
完整的按键检测
一次完整的按键事件
( 1 ) 按键事件就是按键操作过程中的不同状态切换
( 2 ) 一个完整的按键事件包括: 按下事件( 由高变低) 、弹起事件( 由低到高)
( 3 ) 一般都认为发生了一次完整的按键事件才算是用户操作了一次按键, 程序才会去处理按键, 所以在一次完整的按键事件中程序只会去处理一次按键。
#include <reg51.h>
// 当前要处理的是K1,对应P1.0IO口,操控的LED是LED1,对应P0.0
/*********************变量定义************************************/
sbit key1 = P1^0;
sbit key2 = P1^1;
sbit key8 = P1^7;
// 独立数码管的段码表
unsigned char val[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
/*********************************** 函数声明 ***********************/
void AddDisplay(void);
void delay(void);
void delay10ms(void);
/******************************全局变量定义*************************/
unsigned char dnum = 0;
void main(void)
{
unsigned char flag = 0; // 默认状态等于0
while (1)
{
if (key1 == 0)
{
// 发现1次低电平,有可能是按键按下,也有可能是抖动,软件消抖
delay10ms();
if (key1 == 0)
{
// 10ms后还是低电平,说明真的是按键按下了,不是抖动
// 这里说明发现了一个按下事件
//flag = 1;
if (flag == 0)
{
AddDisplay();
flag = 1;
}
}
}
else
{
// 电平 == 1
delay10ms();
if (key1 == 1)
{
// 说明弹起了
if (flag == 1)
{
//AddDisplay();
flag = 0;
}
}
}
delay();
}
}
// 该函数将num数字送到独立数码管去显示
void AddDisplay(void)
{
dnum = dnum + 1;
if (dnum > 15)
{
dnum = 0;
}
P0 = val[dnum];
}
// 延时函数
void delay(void)
{
unsigned char i, j;
for (i=0; i<100; i++)
for (j=0; j<200; j++);
}
void delay10ms(void) //误差 0us
{
unsigned char a,b,c;
for(c=5;c>0;c--)
for(b=4;b>0;b--)
for(a=248;a>0;a--);
}
6)矩阵键盘
#include <reg51.h>
// P0端口接LED
// P0端口接数码管
// P3端口接矩阵键盘
#define LED P0
#define KEY P3
#define DIG P0
// 独立数码管的段码表
unsigned char val[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
/*********************变量定义************************************/
/********************************* 函数声明 ***********************/
unsigned char GetKey(void);
void delay(void);
/******************************全局变量定义*************************/
void main(void)
{
unsigned char key = 0;
while(1)
{
key = GetKey();
if(key != 0)
{
DIG = val[key];
}
}
}
unsigned char GetKey(void)
{
unsigned char hang = 0, lie = 0;
unsigned char keyvalue = 0;
//第1回合第1步
KEY = 0x0f; //从IO口输出,写IO口
if(KEY != 0x0f) //从IO口输入,读IO口
{
//读出的不是0x0f说明有按键被按下
//第1回合第2步,读出端口从读出值来判断哪一行
//第一回合中算出行号
switch(KEY)
{
case 0xfe: hang = 1; break;
case 0xfd: hang = 2; break;
case 0xfb: hang = 3; break;
case 0xf7: hang = 4; break;
default: break;
}
delay();
//第2回合第一步
KEY = 0xf0;
if(KEY != 0xf0)
{
//第二回合中算出行号
switch(KEY)
{
case 0xef: lie = 1; break;
case 0xdf: lie = 2; break;
case 0xbf: lie = 3; break;
case 0x7f: lie = 4; break;
default: break;
}
//经过2个回合后hang和lie都知道了,然后根据hang和lie去计算键值即可
keyvalue = (hang - 1) * 4 + lie;
return keyvalue;
}
}
return 0;
}
// 延时函数
void delay(void)
{
unsigned char i, j;
for (i=0; i<100; i++)
for (j=0; j<200; j++);
}