
在单片机应用系统中,对键盘的处理工作仅是CPU工作内容的一部分,CPU还要进行数据处理、显示和其他输入输出 *** 作,因此键盘处理工作既不能占用CPU太多时间,又需要CPU对键盘 *** 作能及时作出响应。CPU对键盘处理控制的工作方式有以下几种:
(1)程序控制扫描方式
程序控制扫描方式是在CPU工作空余,调用键盘扫描子程序,响应键输入信号要求。程序控制扫描方式的键处理程序固定在主程序的某个程序段。当主程序运行到该程序段时,依次扫描键盘,判断有否键输入。若有,则计算按键编号,执行相应键功能子程序。这种工作方式,对CPU工作影响小,但应考虑键盘处理程序的运行间隔周期不能太长,否则会影响对键输入响应的及时性。
(2)定时控制扫描方式
定时控制扫描方式是利用定时/计数器每隔一段时间产生定时中断,CPU响应中断后对键盘进行扫描,并在有键闭合时转入该键的功能子程序。定时控制扫描方式与程序控制扫描方式的区别是,在扫描间隔时间内,前者用CPU工作程序填充,后者用定时/计数器定时控制。定时控制扫描方式也应考虑定时时间不能太长,否则会影响对键输入响应的及时性。
(3)中断控制方式
中断控制方式是利用外部中断源,响应键输入信号。当无按键按下时,CPU执行正常工作程序。当有按键按下时,CPU立即产生中断。在中断服务子程序中扫描键盘,判断是哪一个键被按下,然后执行该键的功能子程序。这种控制方式克服了前两种控制方式可能产生的空扫描和不能及时响应键输入的缺点,既能及时处理键输入,又能提高CPU运行效率,但要占用一个宝贵的中断资源。
#include <reg51h>
#include <intrinsh>
sbit SPK=P3^4; //SPK定义为P3口的第4位,就是驱动蜂鸣器的那个脚
sbit JDQ=P3^5; //JDQ定义为P3口的第5位,就是驱动继电器的那个脚
code unsigned char table[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};
//共阴数码管 0-9 a-f 表
code unsigned char key_tab[17]={0xed,0x7e,0x7d,0x7b,
0xbe,0xbd,0xbb,0xde,
0xdd,0xdb,0x77,0xb7,
0xee,0xd7,0xeb,0xe7,0XFF};//========================此数组为键盘编码,
//本人采用类式类似电话按键的编码方式,方便以后设计
// 1 2 3 a 0x01 0x02 0x03 0
// 4 5 6 b 对应16进制码: 0x04 0x05 0x06 0x0b
// 7 8 9 d 0x07 0x08 0x09 0x0d
// 0 # f 0x0c 0x00 0x0e 0x0f
//打个比方,如果你按下0键,P0口读到数据为0xed
//如果你按下2键,P0口读到数据为0x7d,按下9键为0xdb,
//我们将读到的P0口数据经过查表法就能得到相应的16进制码
//键盘的读取,我们采用分时扫描
unsigned char l_tmpdate[8]={0,0,0,0,0,0,0,0};//定义数组变量
unsigned char l_key=0x0; //定义变量,存放键值
unsigned char l_keyold=0xFF; //做为按键松开否的凭证
void ReadKey(void); //扫描键盘 获取键值
void delay();//延时子函数,5个空指令
void display(unsigned char lp,unsigned char lc);//数字的显示函数;lp为指向数组的地址,lc为显示的个数
//这个函数在第二节用过不用再说了吧!
void main(void) //入口函数
{
while(1){
ReadKey(); //调用键盘扫描
display(&l_key,1); //输出显示获取的键值码
if(l_key==0x0e) //这里我们检测是否按了0x0e键,
JDQ=0; //是,我们就驱动继电器打开
if(l_key==0x0c) //检测是否按下了0x0c键,
JDQ=1; //是,我们就驱动继电器断开
}
}
void ReadKey(void) //读键盘值
{
unsigned char i,j,key;
//分三个部份来理解,
//第一部份,用扫描来读取键盘,
j=0xfe;
key=0xff; //设定初值
for (i=0;i<4;i++){
P0=j; //P0口低4位循环输出0,扫描键盘
//leday();
if ((P0&0xf0)!=0xf0){ //如果有键按下,P0口高4位不会全为1,
key=P0; //读取P0口,退出循环,否则循环下次
break;
}
j=_crol_(j,1); //此函数功能为左循环移位
}
//第二部份,检测是否干扰或按键放开
if (key==0xff){ //如果读取不到P0口的值,比如是干扰或是键盘又松开,我们做相应复位,返回
l_keyold=0xff;
SPK=1; //按键有松开,停止蜂鸣器响
return;
}
else
SPK=0; //打开蜂鸣器
//第三部份,检测是新按键按下,获取新的键盘编码值
if(l_keyold!=key){ //检测按键放开否,如果一样表明没放开,不做处理,不一样表时另一个键按下做编码转换
l_keyold=key; //获取键码做为放开下次的凭证
for(i=0;i<17;i++){ //查表获得相应的16进制值存放l_key变量中
if (key==key_tab[i]){
l_key=i;
break;
}
}
}
//程序运行到这里,就表明有键值被读取存放于l_key变量中,主程序就可以检测此变量做相应外理,
//此时我们回到主程序
}
void display(unsigned char lp,unsigned char lc)//显示
{
unsigned char i; //定义变量
P2=0; //端口2为输出
P1=P1&0xF8; //将P1口的前3位输出0,对应138译门输入脚,全0为第一位数码管
for(i=0;i<lc;i++){ //循环显示
P2=table[lp[i]]; //查表法得到要显示数字的数码段
delay(); //延时5个空指令
if(i==7) //检测显示完8位否,完成直接退出,不让P1口再加1,否则进位影响到第四位数据
break;
P2=0; //清0端口,准备显示下位
P1++; //下一位数码管
}
}
void delay(void) //空5个指令
{
_nop_();_nop_();_nop_();_nop_();_nop_();
}
keyscan()
{
unsigned int i;
unsigned char key_h, key_l; //定义行列值
P3 = 0xf0; //将行全部置为0
key_l = P3 & 0xf0; //将P3口读入列
if(key_l != 0xf0) { //判断如果有键按下
for(i = 0; i < 25; i++); //延时消抖
key_l = P3 & 0xf0; //将P3口读入列
if(key_l != 0xf0) { //第二次判断
P3 = key_l | 0x0f; //重置P3口使其显示出按键后的状态
key_h = P3 & 0x0f; //读入行
//---------------------------------------------
key_h = key_l + key_h; //保存到key_h
//------------
P3 = 0xf0; //将行全部置为0
while(key_l != 0xf0) //只有处于按下状态
key_l = P3 & 0xf0; //就再次读入
//------------
return(key_h); //释放后返回
//---------------------------------------------
}
}
return 0; //没有按键时返回0
}
代码很好写,但是关键是你的数码管属于硬件
也就是说,至少要知道 *** 作你数码管的API才行啊。
或者说要怎样传送数据给你的数码管,你的数码管需要接受怎样的数据。
键盘扫描很简单,给你个代码。
要求引用头文件
#include <iostream>
using namespace std;
#include <conioh>//kbhit API头文件
#include <timeh>
#include <windowsh>
#define ESC 0x1b
void loop()
{
int i;
if( kbhit() ) //判断是否有键盘按键按下。
{
char ch;
ch = getch(); //获取按下的键值
if( ESC == ch )//判断是否是你要的键,我以ESC为例
{
cout<<"ESC"<<endl;
system("pause");
}
}
while( !kbhit() )//没有按键是的 *** 作
{
balabalabala
}
}
int main()
{
loop();
}
codevalue = m + j; //行号加列号
while (checkkey() != 0);//待松手
return (codevalue); //返回键值
----------
codevalue = m + j; //为行号加列号,
共有两层循环,各循环四次,即有:
j = 0, 1, 2, 3;
m = 0, 4, 8, 12;
于是:
m + j = 0 ~ 15;
没错。
只是程序编写的滥一些,可以化简好多的,
以上就是关于键盘扫描控制方式有哪几种各有什么优缺点全部的内容,包括:键盘扫描控制方式有哪几种各有什么优缺点、按键扫描的keil.c51程序、关于单片机键盘扫描问题(行列转换)等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)