找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5942|回复: 5
收起左侧

独立按键矩阵键盘定时器消抖非延时消抖程序

[复制链接]
ID:349802 发表于 2018-6-14 09:01 | 显示全部楼层 |阅读模式
#include<reg52.h>

sbit KEY_IN_1 = P2^4;
sbit KEY_IN_2 = P2^5;
sbit KEY_IN_3 = P2^6;
sbit KEY_IN_4 = P2^7;
sbit KEY_OUT_1 = P2^3;
sbit KEY_OUT_2 = P2^2;
sbit KEY_OUT_3 = P2^1;
sbit KEY_OUT_4 = P2^0;


unsigned char KeySta[4][4] = {
        {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
        };
unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表
    { 0x31, 0x32, 0x33, 0x26 }, //数字键1、数字键2、数字键3、向上键
    { 0x34, 0x35, 0x36, 0x25 }, //数字键4、数字键5、数字键6、向左键
    { 0x37, 0x38, 0x39, 0x28 }, //数字键7、数字键8、数字键9、向下键
    { 0x30, 0x1B, 0x0D, 0x27 }  //数字键0、ESC键、  回车键、 向右键
        };
void  KeyDriver();
void main()
{
    EA = 1;       //使能总中断
    TMOD = 0x01;  //设置T0为模式1
    TH0  = 0xFC;  //为T0赋初值0xFC67,定时1ms
    TL0  = 0x67;
    ET0  = 1;     //使能T0中断
    TR0  = 1;     //启动T0       
    while (1)
    {
        KeyDriver();   //调用按键驱动函数
    }
}

void KeyAction(unsigned char keycode)                                        //按键处理函数,根据不同键值执行动作
{
       
        if((keycode >= 0x30) &&(keycode <= 0x39))                        //数字键
        {
               
        }
       
        else if(keycode == 0x26)                                                        //向上键
        {
               
        }
        else if(keycode == 0x25)                                                        //向左键
        {
               
        }
        else if(keycode == 0x28)                                                        //向下键
        {
               
        }
        else if(keycode == 0x27)                                                        //向右键
        {
               
        }
        else if(keycode == 0x0D)                                                        //回车键
        {
               
        }
        else if(keycode == 0x1B)                                                        //ESC键
        {
               
        }       
         
}
void  KeyDriver()
{
        unsigned char i, j;
        static        unsigned char backup [4][4] = {
        {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
        };

        for(i=0; i<4; i++)
                {
                        for(j=0; j<4; j++)
                        {
                                if(backup[i][j] != KeySta[i][j])
                                {
                                        if(backup[i][j] == 0)
                                        {
                                                KeyAction(KeyCodeMap[i][j]);
                                        }
                                        backup[i][j] = KeySta[i][j];
                                }
                        }       
                }

       
}

/* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */
void KeyScan()
{
    unsigned char i;
    static unsigned char keyout = 0;   //矩阵按键扫描输出索引
    static unsigned char keybuf[4][4] = {  //矩阵按键扫描缓冲区
        {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF},
        {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF}
    };

    //将一行的4个按键值移入缓冲区
    keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
    keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
    keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
    keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
    //消抖后更新按键状态
    for (i=0; i<4; i++)  //每行4个按键,所以循环4次
    {
        if ((keybuf[keyout][i] & 0x0F) == 0x00)
        {   //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下
            KeySta[keyout][i] = 0;
        }
        else if ((keybuf[keyout][i] & 0x0F) == 0x0F)
        {   //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起
            KeySta[keyout][i] = 1;
        }
    }
    //执行下一次的扫描输出
    keyout++;                //输出索引递增
    keyout = keyout & 0x03;  //索引值加到4即归零
    switch (keyout)          //根据索引,释放当前输出引脚,拉低下次的输出引脚
    {
        case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
        case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
        case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
        case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
        default: break;
    }
}

/* T0中断服务函数,用于数码管显示扫描与按键扫描 */
void InterruptTimer0() interrupt 1
{
        TH0 = 0xFC;
        TL0 = 0x67;
        KeyScan();
}

独立按键矩阵键盘定时器消抖非延时消抖程序.zip

2.07 KB, 下载次数: 32, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:332133 发表于 2018-6-29 13:49 | 显示全部楼层
楼主你好,我用这个矩阵键盘程序有个问题,只在按键第一次按下有效,再次按下就没反应了,遇到过这种情况吗
回复

使用道具 举报

ID:80456 发表于 2018-6-29 14:59 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:349802 发表于 2018-7-5 18:17 | 显示全部楼层
T奉义 发表于 2018-6-29 13:49
楼主你好,我用这个矩阵键盘程序有个问题,只在按键第一次按下有效,再次按下就没反应了,遇到过这种情况吗

不应该吧,这个我是测试过的,需要在1-2ms的定时器中断中调用keyscan(),在主函数中循环调用keydriver(),这个按键扫描按键按下只会执行一次,需要弹开再次按下触发下一次操作,也就是单击
回复

使用道具 举报

ID:205182 发表于 2018-7-5 23:30 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

ID:426132 发表于 2020-7-4 08:01 | 显示全部楼层
楼主:为什么4*4就没问题,4*6怎么调都不行,关键在哪里
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表