找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1996|回复: 3
打印 上一主题 下一主题
收起左侧

在书上看到的程序,总感觉它中断里面的扫描缓存有问题,有兴趣的可以看一下

[复制链接]
跳转到指定楼层
楼主
ID:204609 发表于 2017-7-14 15:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg52.h>

sbit KEY_IN_1  = P2^4;  //矩阵按键的扫描输入引脚1
sbit KEY_IN_2  = P2^5;  //矩阵按键的扫描输入引脚2
sbit KEY_IN_3  = P2^6;  //矩阵按键的扫描输入引脚3
sbit KEY_IN_4  = P2^7;  //矩阵按键的扫描输入引脚4
sbit KEY_OUT_1 = P2^3;  //矩阵按键的扫描输出引脚1
sbit KEY_OUT_2 = P2^2;  //矩阵按键的扫描输出引脚2
sbit KEY_OUT_3 = P2^1;  //矩阵按键的扫描输出引脚3
sbit KEY_OUT_4 = P2^0;  //矩阵按键的扫描输出引脚4
sbit  ADDR0 = P1^0;
sbit  ADDR1 = P1^1;
sbit  ADDR2 = P1^2;
sbit  ADDR3 = P1^3;
sbit  ENLED = P1^4;

unsigned char code LedChar[] = {
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
    0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8e
};  //数码管真值表

unsigned char KeySta[4][4] = {  //全部矩阵按键的当前状态,默认都未按下
    {1, 1, 1, 1},      //bit类型不能定义数组,因此定义成unsigned char
    {1, 1, 1, 1},
    {1, 1, 1, 1},
    {1, 1, 1, 1}
};

void main(void)
{
    unsigned char i, j;
    unsigned char backup[4][4] = {  //按键值备份,保存前一次的值
        {1, 1, 1, 1},
        {1, 1, 1, 1},
        {1, 1, 1, 1},
        {1, 1, 1, 1}
    };

    //选择最右边的数码管进行显示
    P0 = 0xFF;
    ADDR0 = 0;
    ADDR1 = 0;
    ADDR2 = 0;
    ADDR3 = 1;
    ENLED = 0;

    //配置T0工作在模式1,定时1ms
    TMOD = 0x01;
    TH0 = 0xFC;
    TL0 = 0x67;
    TR0 = 1;
    ET0 = 1;
    EA = 1;

    while(1)
    {
        //检索按键状态的变化
        for (i=0; i<4; i++) //i作为行循环变量
        {
            for (j=0; j<4; j++) //j作为列循环变量
            {
                if (backup[j] != KeySta[j]) //判断按键动作
                {
                    if (backup[j] == 0)   //判断按键弹起
                    {
                        P0 = LedChar[i*4+j]; //执行按键动作
                    }
                    backup[j] = KeySta[j]; //更新前一次的值
                }
            }
        }
    }
}

void InterruptTimer0() interrupt 1
{
    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}
    };

    TH0 = 0xFC;  //溢出后进入中断重新赋值
    TL0 = 0x67;                                                                                                   按照我们的键盘扫描程序应该是中断1ms键值赋值一次并赋值
                                         左移4次则keyout加1转下一列重新扫描16ms扫描完成。而此
                                         程序我发现中断1ms虽然会有键值输入缓存但他会输入一次
                                      keyout就增加一次达不到我们所涉及的效果吗。或许我分析的
                                        不对,就请各位看一下

    //将一行的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] & 0x0F) == 0x00)
        {   //连续4次扫描值为0,即16ms(4*4ms)内都只检测到按下状态时,可认为按键已按下
            KeySta[keyout] = 0;
        }
        else if ((keybuf[keyout] & 0x0F) == 0x0F)
        {   //连续4次扫描值为1,即16ms(4*4ms)内都只检测到弹起状态时,可认为按键已弹起
            KeySta[keyout] = 1;
        }
    }

    //执行下一次的扫描输出
    keyout++;
    keyout &= 0x03;  //用跟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;
    }
}


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2017-7-14 17:08 | 只看该作者
这是哪本误人子弟的书,这个例程不值得研究,给你推荐一个例程,程序很简单,一眼看明白:
#include <reg52.h>                                                 //头文件
#define uchar unsigned char                         //宏定义
#define uint unsigned int                                 //宏定义
uchar key=0;                                                        //键值变量

void key_scan()                                                        //矩阵键盘扫描函数
{
        uchar temp1,temp2,temp3;                        //临时变量
        static bit sign=0;                                        //按键自锁标志
        static uchar count=0;                                //消抖计数变量
        P3=0xf0;                                                        //先给P3赋一个初值
        if(P3!=0xf0)                                                 //判断P3不等于所赋初值,说明有健按下
        {
                if(sign==0)                                                //如果按键自锁标志为0
                {
                        count++;                                        //消抖计数
                        if(count>=100)                                //消抖计数自>=100,估算主循环周期调整
                        {                                                        //摒弃Delay延时方式,
                                count=100;                                //防止溢出
                                sign=1;                                        //按键自锁标志置1,键不抬起,按其他键无效
                                temp1=P3;                                //temp1保存高4位变化
                                P3=0x0f;                                //再给P3赋值0x0f
                                temp2=P3;                                //temp2保存低4位变化
                                temp3=temp2|temp1;                //temp3=高4位+低4位
                                key=temp3;                                //保存键值
                        }
                }
        }
        else                                                                 //按键抬起
        {
                sign=0;                                                        //按键自锁标志清0
                count=0;                                                //消抖计数清0
        }
}

void main()
{
        while(1)
        {
                key_scan();                                                //键盘扫描
                P1=key;                                                        //LED低电平亮显示键值
        }                                                                               
}
回复

使用道具 举报

板凳
ID:471066 发表于 2019-2-7 15:21 | 只看该作者
同感,最不喜欢将那些变量名定的又臭又长的

评分

参与人数 7黑币 +182 收起 理由
jinsheng7533967 + 35
zhengchong60 + 15
站着说话不腰疼 + 12
sheng7533967 + 15
shuisheng60 + 35
刀刀见红 + 35
yoxi + 35

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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