矩阵键盘——按下矩阵按键,数码管显示出位置对应的字符(0123 4567 89Ab CdEF)
/*按下矩阵按键,数码管显示出位置对应的字符(0123 4567 89Ab CdEF)*/
#include <>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;//数码管段显
sbit wela=P2^7;//数码管位显
uchar disnum,temp,key,num;
//段显编码的下标(返回值),临时变量,键值,段显编码的下标(调用值)
uchar code table_du[]={//共阴极8段数码管段显编码
0x3f,0x06,0x5b,0x4f,0x66,0x6d, //012345
0x7d,0x07,0x7f,0x6f,0x77,0x7c, //6789Ab
0x39,0x5e,0x79,0x71,0x00}; //CdEF无
void delay(uchar);//声明 延时函数
uchar keyscan();//声明 矩阵键盘扫描函数
void main()
{
disnum=16;//没有按键按下时,默认段显为“无”(不显示)
wela=1;//位显允许写入
P0=0xfe;//1111 1110,仅点亮第一位数码管
wela=0;//位显锁存
while(1)
{
P0=table_du[keyscan()];//预写入段显
/**************************************************************
其实此语句可由以下段落的语句替代:
keyscan(); //获取 段显编码的下标(返回值)
num=disnum; //段显编码的下标(调用值)
P0=table_du[num]; //预写入段显
**************************************************************/
dula=1;//段显允许写入
dula=0;//段显锁存
}
}
/*【我们记 由左到右数第x行,由上到下数第y列 的按键为 key[x,y]】*/
uchar keyscan()//矩阵键盘扫描函数;检测 矩阵按键 中被按下的 按键 的位置信息
{
P3=0xf0;//1111 0000,初始化,令高四位(列)=1,低四位(行)=0
/***********************************************************
如果 某列中有按键被按下,行列接通而短路,
那么 对应列的 P3口高四位 就会 强制 变为0,比如:
若 key[2,3](即S12)被按下,则 P3=1011 0000
************************************************************/
temp=P3;//取此时P3的值(此时的temp仅包含了列的位置信息)
temp=temp&0xf0;//按位与,取高四位(列),低四位(行)置0
if(temp!=0xf0)//如果高四位不全为1,说明为P3口高四位为0的列有按键被按下
{
delay(5);//等10ms,消除 按前 抖动
if(temp!=0xf0)//如果高四位真的不全为1,说明该列真的有按键被按下
{
temp=P3;//取此时P3的值(此时的temp仅包含了列的位置信息)
temp=temp|0x0f;//按位或,保留高四位(列)的值,低四位(行)置1
P3=temp;//P3口输出这个数(对应的高低电平)
/*由于P3高四位中对应该按键的列为0,此时按键还未松开,
行列接通而短路,那么其对应行的P3口低四位就会 强制 为0*/
key=P3;//记录此时P3的值(此处key的值已经包含行列的全部位置信息)
switch(key)
{//不同的key代表着不同的按键被按下
//那么,就可以根据key来确定要输出的字符的段显编码的下标
case 0xee:disnum=0;//key[1,1](S6) 1110 1110
break; /*列 行*/
case 0xde:disnum=1;//key[1,2](S7) 1101 1110
break;
case 0xbe:disnum=2;//key[1,3](S8) 1011 1110
break;
case 0x7e:disnum=3;//key[1,4](S9) 0111 1110
break;
case 0xed:disnum=4;//key[2,1](S10) 1110 1101
break;
case 0xdd:disnum=5;//key[2,2](S11) 1101 1101
break;
case 0xbd:disnum=6;//key[2,3](S12) 1011 1101
break;
case 0x7d:disnum=7;//key[2,4](S13) 0111 1101
break;
case 0xeb:disnum=8;//key[3,1](S14) 1110 1011
break;
case 0xdb:disnum=9;//key[3,2](S15) 1101 1011
break;
case 0xbb:disnum=10;//key[3,3](S16) 1011 1011
break;
case 0x7b:disnum=11;//key[3,4](S17) 0111 1011
break;
case 0xe7:disnum=12;//key[4,1](S18) 1110 0111
break;
case 0xd7:disnum=13;//key[4,2](S19) 1101 0111
break;
case 0xb7:disnum=14;//key[4,3](S20) 1011 0111
break;
case 0x77:disnum=15;//key[4,4](S21) 0111 0111
break;
}
}
}
return disnum;//返回要输出的字符的段显编码的下标
}
void delay(uchar x)//延时函数
{
uchar a,b;
for(a=x;a>0;a--)
for(b=200;b>0;b--);
}