经典的矩阵键盘扫描程序
查找哪个按键被按下的
方法
快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载
为:一个一个地查找。
先第一行输出0,检查列线是否非全高;
否则第二行输出0,检查列线是否非全高;
否则第三行输出0,检查列线是否非全高;
如果某行输出0时,查到列线非全高,则该行有按键按下;
根据第几行线输出0与第几列线读入为0,即可判断在具体什么位置的按键按下。
下面是具体程序:
void Check_Key(void)
{
unsigned char row,col,tmp1,tmp2;
tmp1 = 0x10; //tmp1用来设置P1口的输出,取反后使P1.4~P1.7中有一个为0
for(row=0;row<4;row++) // 行检测
{
P1 = 0x0f; // 先将p1.4~P1.7置高
P1 =~tmp1; // 使P1.4~p1.7中有一个为0
tmp1*=2; // tmp1左移一位
if ((P1 & 0x0f) < 0x0f) // 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测
{
tmp2 = 0x01; // tmp2用于检测出哪一列为0
for(col =0;col<4;col++) // 列检测
{
if((P1 & tmp2)==0x00) // 该列如果为低电平则可以判定为该列
{
key_val =key_Map[ row*4 +col ]; // 获取键值,识别按键;key_Map为按键的定义表
return; // 退出循环
}
tmp2*=2; // tmp2左移一位
}
}
}
} //结束
这是一种比较经典的矩阵键盘识别方法,实现起来较为简单,程序短小精炼。
4*4矩阵键盘扫描程序
/*
设置行线为输入线,列线为输出线
*/
uchar KeyScan(); //按键扫描子程序
void delay10ms(); //延时程序
uchar key_free(); //等待按键释放程序
void key_deal(); //键处理程序
//主程序
void main()
{
while(1)
{
KeyScan();
key_free();
key_deal();
}
}
//按键扫描子程序
uchar KyeScan()
{
unsigned char key,temp;
P1=0xF0;
if(P1&0xF0!=0xF0)
{
delay10ms(); //延时去抖动
if(P1&0xF0!=0xF0)
{
P1=0xFE; //扫描第一列
temp=P1;
temp=temp&0xF0;
if(temp!=0xF0) //如果本列有键按下
{
switch(temp)
{
case 0xE0: //第一行有键按下
key=0;break;
case 0xD0: //第二行有键按下
key=4;break;
case 0xB0: //第三行有键按下
key=8;break;
case 0x70: //第四行有键按下
key=12;break;
}
}
P1=0xFD; //扫描第二列
temp=P1;
temp&=0xF0;
if(temp!=0xF0)
{
switch(temp)
{
case 0xE0: //第一行有键按下
key=1;break;
case 0xD0: //第二行有键按下
key=5;break;
case 0xB0: //第三行有键按下
key=9;break;
case 0x70: //第四行有键按下
key=13;break;
}
}
P1=0xFb; //扫描第三列
temp=P1;
temp&=0xF0;
if(temp!=0xF0)
{
switch(temp)
{
case 0xE0: //第一行有键按下
key=2;break;
case 0xD0: //第二行有键按下
key=6;break;
case 0xB0: //第三行有键按下
key=10;break;
case 0x70: //第四行有键按下
key=14;break;
}
}
P1=0xF7; //扫描第四列
temp=P1;
temp&=0xF0;
if(temp!=0xF0)
{
switch(temp)
{
case 0xE0: //第一行有键按下
key=3;break;
case 0xD0: //第二行有键按下
key=7;break;
case 0xB0: //第三行有键按下
key=11;break;
case 0x70: //第四行有键按下
key=15;break;
}
}
}
return(key);
}
}
//延时程序
void delay10ms()
{
unsigned char i,j;
for(i=0;i<10;b++)
for(j=0;j<120;j++)//延时1ms
{
}
}
//等待按键释放程序
uchar key_free()
{
key=key_scan(); //取扫描到的键值
P1=0xF0;//置行线全为高电平,列线全为低电平
wheile(P1&0xF0!=0xF0) //如果仍有键按下
{
}
return(key);//返回键值
}
51单片机矩阵键盘扫描、数码管显示键值实验
/***********************************************
程序名称:矩阵键盘扫描显示键值
简要说明:P1口接矩阵键盘:低四位列,高四位行
使用共阳型数码管:
P0口输出数码管段码,P2口输出数码管位码
编 写:JiangX.net
***********************************************/
#include
#define uchar unsigned char;
uchar key_val=0; //定义键值,初始默认为0
uchar code TAB[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xC6,0xa1,0x86,0x8e}; //0~F共阳数码管显示段码
/*****按键扫描*****/
void Check_Key(void)
{
unsigned char row,col,tmp1,tmp2;
tmp1 = 0x10; //tmp1用来设置P1口的输出,取反后使P1.4~P1.7中有一个为0
for(row=0;row<4;row++) // 行检测
{
P1 = 0x0f; // 先将p1.4~P1.7置高
P1 =~tmp1; // 使P1.4~p1.7中有一个为0
tmp1*=2; // tmp1左移一位
if ((P1 & 0x0f) < 0x0f) // 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测
{
tmp2 = 0x01; // tmp2用于检测出哪一列为0
for(col =0;col<4;col++) // 列检测
{
if((P1 & tmp2)==0x00) // 该列如果为低电平则可以判定为该列
{
key_val = row*4 +col; // 获取键值,识别按键
return; // 退出循环
}
tmp2*=2; // tmp2左移一位
}
}
}
}
/*****主函数,显示键值*****/
void main()
{
P2=0x00; //位码,这里全部置低,点亮8位数码管(见视频效果)
while(1)
{
Check_Key();
P0=TAB[key_val]; //显示
}
}
实验7 矩阵按键识别技术
矩阵按键部分由16个轻触按键按照4行4列排列,连接到JP50端口。将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。这样,当按键没有按下时,所有的输出端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。
确定矩阵式键盘上何键被按下,介绍一种“行扫描法”。
行扫描法行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法.
判断键盘中有无键按下:将全部行线置低电平,然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。若所有列线均为高电平,则键盘中无键按下。
判断闭合键所在的位置:在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。
下面给出一个具体的例子:
8031单片机的P1口用作键盘I/O口,键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。列线P1.0-P1.3设置为输入线,行线P1.4-P.17设置为输出线。4根行线和4根列线形成16个相交点。
1,检测当前是否有键被按下。检测的方法是P1.4-P1.7输出全“0”,读取P1.0-P1.3的状态,若P1.0-P1.3为全“1”,则无键闭合,否则有键合。
2,去除键抖动。当检测到有键按下后,延时一段时间再做下一步的检测判断。
3.若有键被按下,应识别出是哪一个键闭合。方法是对键盘的行线进行扫描。P1.4-P1.7按下述4种组合依次输出:
P1.7 1 1 1 0
P1.6 1 1 0 1
P1.5 1 0 1 1
P1.4 0 1 1 1
在每组行输出时读取P1.0-P1.3,若全为“1”,则表示为“0”这一行没有键闭合,否则有键闭合。由此得到闭合键的行值和列值,然后可采用计算法或查表法将闭合键的行值和列值转换成所定义的键值。
4,为了保证键每闭合一次CPU仅作一次处理,必须去除键释放时的抖动。
实验目的:通过XL2000的16位矩阵按键,在数码管上分别显示0---9,A,B,C,D,E,F。
接线方法:1,用一条8PIN数据排线,把矩阵按键部份的JP50,接到CPU部份的P1口JP44.
2,接8位数码管的数据线。将数码管部份的数据口 JP5接到CPU部份的P0口JP51.
3,接8位数码管的显示位线。将数码管部份的显示位口 JP8接到CPU部份的P2口JP52.
参考程序:
;本程序实现扫描按键显示功能.
;分别按16个键盘显示分别显示数字123A456B789C*0#D
;键盘口P1,数码管显示第二位p21, 数码管段位p0口
org
0000h
ajmp
main
org
0030h
main:
mov
dptr,#tab
;将表头放入DPTR
lcall
key
;调用键盘扫描程序
movc
a,@a+dptr ;查表后将键值送入ACC
mov
p0,a ;将Acc值送入P0口
CLR P2.1 ;开显示
ljmp
main ;返回反复循环显示
KEY: LCALL KS ;调用检测按键子程序
JNZ K1 ;有键按下继续
LCALL DELAY2 ;无键按调用延时去抖
AJMP KEY ;返回继续检测按键
K1: LCALL DELAY2
LCALL DELAY2 ;有键按下延时去抖动
LCALL KS ;再调用检测按键程序
JNZ K2 ;确认有按下进行下一步
AJMP KEY ;无键按下返回继续检测
K2:
MOV R2,#0EFH ;将扫描值送入 R2暂存
MOV R4,#00H ;将第一列值送入R4暂存
K3:
MOV P1,R2 ;将R2的值送入P1口
L6:
JB P1.0,L1 ;P1.0等于1跳转到L1
MOV A,#00H ;将第一行值送入ACC
AJMP LK ;跳转到键值处理程序
L1:
JB P1.1,L2 ;P1.1等于1跳转到L2
MOV A,#04H ;将第二行的行值送入ACC
AJMP LK ;跳转到键值理程序进行键值处理
L2: JB P1.2,L3 ;P1.2等于1跳转到L3
MOV A,#08H ;将第三行的行值送入ACC
AJMP LK ;跳转到键值处理程序
L3:
JB P1.3,NEXT ;P1.3等于1跳转到NEXT处
MOV A,#0cH ;将第四行的行值送入ACC
LK:
ADD A,R4 ;行值与列值相加后的键值送入A
PUSH ACC ;将A中的值送入堆栈暂存
K4: LCALL DELAY2 ;调用延时去抖动程序
LCALL KS ;调用按键检测程序
JNZ K4 ;按键没有松开继续返回检测
POP ACC ;将堆栈的值送入ACC
RET
NEXT:
INC R4 ;将列值加一
MOV A,R2 ;将R2的值送入A
JNB ACC.7,KEY ;扫描完至KEY处进行下一扫描
RL A ;扫描未完将A中的值右移一位进行下一列的扫描
MOV R2,A ;将ACC的值送入R2暂存
AJMP K3 ;跳转到K3继续
KS:
MOV P1,#0FH ;将P1口高四位置0低四位值1
MOV A,P1 ;读P1口
XRL A,#0FH ;将A中的值与A中的值相异或
RET ;子程序返回
DELAY2: ;40ms延时去抖动子程序
MOV R5,#08H
L7:
MOV R6,#0FAH
L8:
DJNZ R6,L8
DJNZ R5,L7
RET
tab:
db 28h,34h,28h,34h,0a9h,60h,20h,7ah,
20h,21h,61h,74h,30h,62h,0a2h,7eh
;0h0hc9878654a321 轮流显示键盘因为无法表达*# 就用H表示,B用8表示
end
矩阵按键与数码管显示的运行照片
3x4矩阵键盘的扫描程序(C语言)
3x4矩阵键盘的扫描程序(C语言)
按相应的按键,数码管显示相应的数字,星号键和井号键分别显示为E和F
#include
unsigned char code table[]={0xC0,0xF9,0xA4,0xB0,0x99, //0~4
0x92,0x82,0xF8,0x80,0x90, //5~9
0x88,0x83,0xA7,0xA1,0x86,0x8E}; //A~F
void KeyScan();
void delay10ms(unsigned char time);
void Dispaly(unsigned char k);
unsigned char key,temp;
void main() //主程序
{
while(1)
{
KeyScan();
}
}
void KeyScan() //按键扫描子程序
{
P1=0xFF;
P1_3=0;
temp=P1;
temp&=0xF0;
if(temp !=0xF0)
{
delay10ms(1);
temp=P1;
temp&=0xF0;
if(temp !=0xF0)
{
temp=P1;
temp&=0xF0;
switch(temp)
{
case 0x70:
key=1;break;
case 0xB0:
key=2;break;
case 0xD0:
key=3;break;
}
Dispaly(key);
}
}
P1=0xFF;
P1_2=0;
temp=P1;
temp&=0xF0;
if(temp !=0xF0)
{
delay10ms(1);
temp=P1;
temp&=0xF0;
if(temp !=0xF0)
{
temp=P1;
temp&=0xF0;
switch(temp)
{
case 0x70:
key=4;break;
case 0xB0:
key=5;break;
case 0xD0:
key=6;break;
}
Dispaly(key);
}
}
P1=0xFF;
P1_1=0;
temp=P1;
temp&=0xF0;
if(temp !=0xF0)
{
delay10ms(1);
temp=P1;
temp&=0xF0;
if(temp !=0xF0)
{
temp=P1;
temp&=0xF0;
switch(temp)
{
case 0x70:
key=7;break;
case 0xB0:
key=8;break;
case 0xD0:
key=9;break;
}
Dispaly(key);
}
}
P1=0xFF;
P1_0=0;
temp=P1;
temp&=0xF0;
if(temp !=0xF0)
{
delay10ms(1);
temp=P1;
temp&=0xF0;
if(temp !=0xF0)
{
temp=P1;
temp&=0xF0;
switch(temp)
{
case 0x70:
key=14;break;
case 0xB0:
key=0;break;
case 0xD0:
key=15;break;
}
Dispaly(key);
}
}
}
//延时程序
void delay10ms(unsigned char time)
{
unsigned char a,b,c;
for(a=0;a