第十二讲——键盘扫描知识

矩阵键盘扫描一般采取行列扫描法。比如先拉低所有列线,拉高行线,之后读取行线状态,如果行线有一行为低,则假设有按键按下,此时再延时20毫秒左右后判断 行线的某一行是否仍然为低,若为低则确认有键按下。这时可以进行按键键值判断,即判别在哪一行哪一列有按键按下。判断的方法是通过拉高列线,依次置行线的 某一行为低,读取列线值。如果列线有一列为低,则表示按键发生在该行,进而可以通过读取到的列线值确定在哪一列,从而确定按键发生在具体的行和列。为了防 止按键按下后一直有按键被读取,需要在程序中设定在按键被释放后才能读取具体的键值来避免这一问题。
代码如下:

#include<reg52.h>
#include<stdio.h>
#define KEY_PORT P2        //矩阵键盘端口,其中P2.0-P2.3为列线,P2.4-P2.7为行线
typedef unsigned char uchar;
typedef unsigned int uint;
void serial_init(void)                       //串口初始化函数
{
   TMOD = 0x20;                              //T1工作方式1,用于设定波特率
   TH1  = 0xF3;                              //波特率4800Bps,12MHz晶振
   TL1  = 0xF3;
   PCON |= 0x80;                             //SMOD = 1,波特率加倍
   SCON = 0x50;                              //允许发送接收
   ES   = 0;                                 //禁止串口中断
   TI   = 1;
   TR1  = 1;
}

uchar key_scan(void)            //键盘扫描函数,有键按下则返回1,否则返回0
{
    uchar keyPressed = 0;
    KEY_PORT = 0xF0;                    //置低列线,以读取行线判断是不是有键按下
    keyPressed = KEY_PORT & 0xF0;        //读取行线值
    if(keyPressed == 0xF0)              //无键按下
        return 0;
    else
        return 1;                        //有键按下
}
uchar key_assert(void)        //键值判断函数,第半字节存列号,高半字节存行号
{
    uchar keyvalue;    //按键键值存储变量,高四位代表行线位置,低四位代表列线位置
    KEY_PORT = 0xEF;//拉低第一行
    if((keyvalue = KEY_PORT & 0x0F) != 0x0F) //第一行的键被按下,确认在哪一列
    {    
        while((KEY_PORT & 0x0F) != 0x0F);         //等待按键释放
        return keyvalue | 0xE0;
    }        
    KEY_PORT = 0xDF;                         //拉低第二行
    if((keyvalue = KEY_PORT & 0x0F) != 0x0F) //第二行的键被按下
    {    
        while((KEY_PORT & 0x0F) != 0x0F);         //等待按键释放
        return (keyvalue | 0xD0);
    }
    KEY_PORT = 0xBF;                         //拉低第三行
    if((keyvalue = KEY_PORT & 0x0F) != 0x0F) //第三行的键被按下
    {    
        while((KEY_PORT & 0x0F) != 0x0F);         //等待按键释放
        return (keyvalue | 0xB0);
    }
    KEY_PORT = 0x7F;                         //拉低第四行
    if((keyvalue = KEY_PORT & 0x0F) != 0x0F) //第四行的键被按下
    {    
        while((KEY_PORT & 0x0F) != 0x0F);         //等待按键释放
        return (keyvalue | 0x70);            
    }
}
void Hardware_Delay_1ms(void)            //硬件定时器延时1ms函数
{
   TMOD &=0xF0;
   TMOD |=0x01;  //T0——16位定时器器模

   TH0 = 0xFC;
   TL0 =0x18;    //64536
  
   TF0=0;        //清除定时器溢出标志
   TR0=1;         //启动定时器    
   while(TF0==0);//等待计数完成
   TR0=0;         //停止定时器
}
void Delay_Nms(uint N)                    //延时N毫秒函数
{
    uint j;
    for(j=N;j>0;j--)
     Hardware_Delay_1ms();    
}
void main(void)
{
    uchar key_value = 0;    //键值
    serial_init();
    while(1)
    {
        if(key_scan())
        {
            Delay_Nms(20);   //延时20ms,去抖
            if(key_scan())   //确实有键按下,读取键值
                key_value = key_assert();  //读取P2值做判断
            P1 = key_value;     //通过LED显示键值
            switch(key_value)//通过串口打印哪个按键被按下信息
            {
                case 0xEE:
                    printf("Key 1 pressed!/n");
                    break;
                case 0xED:
                    printf("Key 2 pressed!/n");
                    break;
                case 0xEB:
                    printf("Key 3 pressed!/n");
                    break;
                case 0xE7:
                    printf("Key 4 pressed!/n");
                    break;
                case 0xDE:
                    printf("Key 5 pressed!/n");
                    break;
                case 0xDD:
                    printf("Key 6 pressed!/n");
                    break;
                case 0xDB:
                    printf("Key 7 pressed!/n");
                    break;
                case 0xD7:
                    printf("Key 8 pressed!/n");
                    break;
                case 0xBE:
                    printf("Key 9 pressed!/n");
                    break;
                case 0xBD:
                    printf("Key 10 pressed!/n");
                    break;
                case 0xBB:
                    printf("Key 11 pressed!/n");
                    break;
                case 0xB7:
                    printf("Key 12 pressed!/n");
                    break;
                case 0x7E:
                    printf("Key 13 pressed!/n");
                    break;
                case 0x7D:
                    printf("Key 14 pressed!/n");
                    break;
                case 0x7B:
                    printf("Key 15 pressed!/n");
                    break;
                case 0x77:
                    printf("Key 16 pressed!/n");
                    break;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岛上码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值