Board logo

标题: 矩阵键盘C51程序(4*4)(来自互联网) [打印本页]

作者: wxg1988    时间: 2011-12-3 20:02     标题: 矩阵键盘C51程序(4*4)(来自互联网)

#include <reg51.h>
#include <intrins.h>
#define key_port P0     //键盘接口定义
sbit key_port_0=key_port^0;
sbit key_port_1=key_port^1;
sbit key_port_2=key_port^2;
sbit key_port_3=key_port^3;
/*******************************
STC89C59 单片机一毫秒延时函数
*******************************/
void delay_ms(unsigned int ms)     
{
     unsigned int i,j;
  
for( i=0;i<ms;i++)
    for(j=0;j<332;j++); //1947是STC89C58在22.1184MHz晶振下,通过软件仿真反复实验得到的数值
}
/**************************
    串口发送一个字符
**************************/
void com_send_dat( unsigned char dat)
{
    SBUF=dat;
while (TI== 0);
TI= 0 ;
}
/**************************
    串口初始化
**************************/
void init_com( void )
{
SCON=0x50 ;     //SCON: serail mode 1, 8-bit UART, enable ucvr    //UART为模式1,8位数据,允许接收
     TMOD|=0x20 ;     //TMOD: timer 1, mode 2, 8-bit reload             //定时器1为模式2,8位自动重装
TH1=0xfa ;         //Baud:19200 fosc="22.1184MHz
TL1=0xfa;
PCON|=0x80;     //SMOD=1;波特率加倍;   
ES=1;       //Enable Serial Interrupt
TR1 = 1 ;        // timer 1 run
}
/**************************
    键盘扫描函数
**************************/
unsigned char keyscan(void)
{
unsigned char key,i;
    unsigned char code key_table[16]=
{0xee,0xed,0xeb,0xe7,0xde,0xdd,0xdb,0xd7,0xbe,0xbd,0xbb,0xb7,0x7e,0x7d,0x7b,0x77};
    key_port=0x0f;            //
确定行列位置
    if(key_port==0x0f)return(0);//
无键按下返回0
    delay_ms(10);               //
调用延时函数
,目的是去前沿键抖。
     if(key_port==0x0f)return(0);//
再次判断。目的是确保检测正确
    else
     {
    for(i=0;i<4;i++)        //
以下为经典的计算键值(判断闭合键所在的位置)
         {
     P0=_cror_(0x7f,i);
     if(key_port_0==0)break;
           if(key_port_1==0)break;
           if(key_port_2==0)break;
           if(key_port_3==0)break;
         }
      key=key_port;          //
取得键值
    for(;key_port!=0x0f; key_port=0x0f);    //
等待键松开,目的是去后沿键抖
    for(i=0;key_table!=key && i<16;i++); //
查表取key的值0-F
    key=i;
     return(key);                           //
带键值返回主调函数
}
}
/**************************
   
键盘扫描测试主函数
**************************/
void main(void)
{
unsigned char key;
init_com(); //
串口初始化
while(1)
{
    key=keyscan();
    if(key!=0)
    {
    com_send_dat(key);
    delay_ms(200);
    }
}
}
2222222222222222222222222222222222222222222222222222222222222222222222222222矩阵键盘扫描程序
按键扫描(线反转)
//-------------------------------- ------------------------------------------------------------------
// 函数名称: program_SCANkey
// 函数功能: 程序扫描键盘,
//                   有键按下完成按键处理,无键按下直接返回
//--------------------------------------------------------------------------------------------------
void program_SCANkey()
{
unsigned char key_code;

           if(judge_hitkey())                    //判断是否有键按下
{
               delay(1000);
                          //延时20ms左右,消除抖动干扰
               if(judge_hitkey())                    //判断是否有效按键
  
{
                   key_code=scan_key();
            //获取键值
             while(judge_hitkey());           //等待按键释放
         {
          }
                   key_manage(key_code);
            //键盘扫描、键盘散转、按键处理
        }
}
}

//--------------------------------------------------------------------------------------------------
// 函数名称: judge_hitkey
// 函数功能: //判断是否有键按下,有返回1,没有返回0
// 列判断,还可以用行判断。
//--------------------------------------------------------------------------------------------------
bit judge_hitkey()                             //判断是否有键按下,有返回1,没有返回0
{
unsigned char scancode,keycode;

scancode=0x0F;                //开始设定P1.0~P1.3输出全1(初值)即表明无键闭合
KEY=scancode;         
keycode=KEY;                  //读取P1.0~P1.3的真实状态,从而确定有没有键被按下
if(keycode==0x0F)
      return(0);                               //全1则无键闭合
else
            return(1);
                               //否则有键闭合
}
//--------------------------------------------------------------------------------------------------
// 函数名称: scan_key
// 函数功能: //扫描键盘,返回键值(高四位代表行,低四位代表列)
// 说明:scancode 扫描码,keycode 键值,keycode_line 行,keycode_row 列
// 过程:先扫描行,确定那行的按键被按下。再扫描列,确定那列的按键被按下,从而确定那个按键被按下。
//--------------------------------------------------------------------------------------------------
unsigned char scan_key()                     //扫描键盘,返回键值(高四位代表行,低四位代表列)
{
          unsigned char scancode,keycode,keycode_line,keycode_row;

    scancode=0xF0;                //列置低,行置高
    KEY = scancode;               //输入扫描码,扫描行
    keycode_line=KEY;             //KEY的值是与键盘相连的P的状态值。若没有按键按下KEY的值为0xF0,若有按键按下则KEY的值就不是0xF0
   
    scancode=0x0F;                             //列置高,行置低
    KEY=scancode;                              //输入扫描码,扫描列
    keycode_row=KEY;          //KEY的值是与键盘相连的P的状态值。若没有按键按下KEY的值为0x0F,若有按键按下则KEY的值就不是0x0F
          keycode = ((keycode_line&0xF0)|(keycode_row&0x0F));
          return(keycode);
}






作者: wxg1988    时间: 2011-12-3 20:03

2、按键扫描(逐行扫描)
//--------------------------------------------------------------------------------------------------
// 函数名称: kbscan         键盘扫描子程序
// 函数功能: 判断是否有键按下,有返回键值,没有返回0
// p1的高四位为列,低四位为行          P1.7          P1.6         P1.5         P1.4         P1.3         P1.2         P1.1         P1.0
//                                     列4          列3           列2          列1          行4          行3          行2           行1
// 过程:先根据列判断是否有键按下,没有返回0,有,则逐行扫描以确定按键所在的行,再确定按键所在列
//             从而最终确定该按键。
//--------------------------------------------------------------------------------------------------
uchar kbscan(void)
{
uchar sccode,recode;
P1=0xf0;                       //置所有行为低电平,行扫描,列线输入(此时)
if((P1&0xf0)!=0xf0)            //判断是否有有键按下(读取列的真实状态,若第4列有键按下则P1的值会变成0111 0000),有往下执行
{
        delays();                   //延时去抖动(10ms)
   if((P1&0xf0)!=0xf0)         //再次判断列中是否是干扰信号,不是则向下执行
        {
         sccode=0xFE;                 //逐行扫描初值(即先扫描第1行)
    while((sccode&0x10)!=0)        //行扫描完成时(即4行已经全部扫描完成)sccode为1110 1111 停止while程序     
    {
     P1=sccode;                     //输出行扫描码
          if ((P1&0xf0)!=0xf0)           //本行有键按下(即P1(真实的状态)的高四位不全为1)
     {
           recode=(P1&0xf0)|0x0f; //列
      return(sccode&recode); //返回行和列
     }
          else             //所扫描的行没有键按下,则扫描下一行,直到4行都扫描,此时sccode值为1110 1111 退出while程序
         {
           sccode=(sccode<<1)|0x01;//行扫描码左移一位
          }
         }
        }
}
          else
{
           return 0;        //无键按下,返回0
}

}
3333333333333333333333333333333333333333333333333333333333333333333333333
C51矩阵键盘控制程序
矩阵键盘依次编号为
0~15,按下任一键会在数码管上显示相应数字(
10~15分别对应
A~F)
P0为数码管段选端,
P1为数码管位选端
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar temp,num;
uchar code
tabledu[]={0xc0/*0*/,0xf9/*1*/,0xa4/*2*/,0xb0/*3*/,0x99/*4*/,0x92/*5*/,0x82/*6*/,0xf8/*7*/,0
x80/*8*/,0x90/*9*/,0x88/*A*/,0x83/*b*/,0xc6/*C*/,0xa1/*d*/,0x86/*E*/,0x8e/*F*/,0x7f};
uchar code tablewe[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//数码管段选数组
uint keyscan();//键盘扫描程序
void delay(uchar x);//延时程序
void display(uint d);//数码管显示程序
void main()
{
uint num1;
num=16;
P0=tabledu[num];
while(1)
{

num1=keyscan();
display(num1);

}
}
void display(uint d)
{
P2=0xfe;
P0=tabledu[d];
}
uint keyscan()
{
P1=0xfe;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{

delay(5);//按下防抖
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)//确认不是干扰
{

temp=P1;//再次赋值
switch(temp)


{
case 0xee:num=0;
break;
case 0xde:num=1;
break;
case 0xbe:num=2;
break;
case 0x7e:num=3;
break;
}
/*while(temp!=0xf0)//松手检测

{
temp=P1;
temp=temp&0xf0;
}
delay(5);//松手防抖*/
}
}
P1=0xfd;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{

temp=P1;
switch(temp)
{
case 0xed:num=4;
break;
case 0xdd:num=5;
break;
case 0xbd:num=6;
break;
case 0x7d:num=7;
break;
}
/*while(temp!=0xf0)//松手检测

{
temp=P1;
temp=temp&0xf0;

}
delay(5);*/
}
}
P1=0xfb;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{

temp=P1;
switch(temp)
{
case 0xeb:num=8;
break;
case 0xdb:num=9;
break;
case 0xbb:num=10;
break;
case 0x7b:num=11;
break;
}
/*while(temp!=0xf0)//松手检测

{
temp=P1;
temp=temp&0xf0;
}
delay(5);*/
}
}
P1=0xf7;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{


temp=P1;
switch(temp)
{
case 0xe7:num=12;
break;
case 0xd7:num=13;
break;
case 0xb7:num=14;
break;
case 0x77:num=15;
break;
}
/*while(temp!=0xf0)//松手检测
{
temp=P1;
temp=temp&0xf0;
}
delay(5);*/
}
}
return num;

}
void delay(uchar x)//延迟
1毫秒
{
uchar a,b,c;
for(c=x;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0