• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

关于51单片机的矩阵键盘扫描的两种方法的困惑,高手解答~

aa32786307ea50da 2019-02-27 浏览量:1286
一般的按键查询法有2种:
(1)把键盘程序放在主程序的while(1)循环里不停的查询。
  
(2)
为防漏键,将按键程序放在定时器0的中断服务程序里,约每10ms中断一次;其返回键值赋给一个全局变量key_value,然后在主函数里将根据key_value的值来做出相应的动作!
        分析上述两种方法:对于第一种方法,如果主程序特别长且很消耗时间,那么很可能出现按键漏扫的情况,不可靠。第二种情况是每隔段时间就去扫描下按键,理论上和主程序的while(1)循环里代码是否长和消耗时间应该无关,应该是很可靠的一种按键扫描方法!但事实就不是这样,下面请看代码,很简单的哦~
//用定时器中断扫描矩阵键盘程序
#include <reg52.h>
#define s8 signed char
#define u8 unsigned char
#define u16  unsigned int
#define u32  unsigned long int
//#define PORT P1
//共阳极不带小数点
u8 code segment[]  = {0XC0 0XF9 0XA4 0XB0 0X99 0X92 0X82 0XF8 
                               0X80 0X90 0X88 0X83 0XC6 0XA1 0X86 0X8E};
u8 code position[] = {0XFE0XFD0XFB0XF70XEF0XDF0XBF0X7F0X000XFF};
u8 key_value = 20u;//u表示无符号整型
u16 tmr0_value = 10000u;
void rough_delay_1ms(u16);
void digitron_static_display(u8 u8); 
void init_tmr0(void);
u8 scan_MatrixKey(void); 

int main(void)
{
     init_tmr0();//初始化定时器0
     while (1)
    {
        //用7段数码管将矩阵键盘的键值显示出来
        digitron_static_display(key_value 8);//8表示位选全开
        //此处延时后按键就不灵敏了,注销延时则按键很灵敏
        rough_delay_1ms(20);//
    }
 
 return 0;
}
//翻转扫描法
u8 scan_MatrixKey(void)
{
    //为了不分散大家注意力,此处的代码就省略了!
}
//初始化定时器0
void init_tmr0(void)
{
 TMOD = 0x01;//设置tmr0为工作方式1
 EA = 1;//开总中断
 ET0 = 1;//开定时器0中断
 TH0 = (65535u - tmr0_value) >> 8;//得到高8位
 TL0 = (65536u - tmr0_value) & 0x00ff;//得到低8位
 TR0 = 1;//启动定时器0
 
    return;
}
//注:定时器溢出后若没重装初值就重新从0开始计数(0—65535)
//计数到65536就溢出!
void tmr0(void) interrupt 1//定时器0中断
{   
    TR0 = 0;//关闭定时器0
    //重新给定时器0赋初值
    TH0 = (65536u - tmr0_value) >> 8;
    TL0 = (65536u - tmr0_value) & 0x00ff;
    key_value = scan_MatrixKey();//扫描矩阵键盘
    TR0 = 1;//启动定时器0
 
    return;
}
//数码管静态显示函数(i对应段选,j对应位选)               
void digitron_static_display(u8 i u8 j)

    if (i>=0 && i<=15u)//过滤除键值以外的数值
    {
        P0 = segment;
        P2 = position[j];
    }
    
 return; 
}
void rough_delay_1ms(u16 t)//粗略延时t毫秒
{
    u16 i;
    for (; t>0; --t)
    {
        for (i=115u; i>0; --i);
    }
    
    return;
}
        现象:注销主程序里的while(1)循环里的延时后,按键非常灵敏,很难出错!但延时20ms后,按 按键 就经常没反应,有时要按好几次才有反应;延时100ms的话,按键几乎就很难有反应了,按半天都没动静!
       困惑:理论上,用定时器定期扫描的方法应该和主程 while(1)循环里的代码无关呀,这种异常现象是怎么回事呀?急求高人解答啊!
0 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
最佳答案
  • 定时器是和main函数无关但是跟定时器程序里的延时有关

    比如你定时时间是10ms

    你在定时器里总延时大于10ms这样的话程序不确定

    程序还没有执行完就退出了 导致未知问题 或者卡顿现象

    • 发布于 2019-02-27
    • 举报
    • 评论 0
    • 0
    • 0

其他答案 数量:8
  • 主要还是延时时间太短,本来按键判断就要100ms左右延时,确定按键是否按下,不要太精确控制延时,特别是写得比较多的时候!要控制时序!
    • 发布于2019-02-27
    • 举报
    • 评论 0
    • 0
    • 0

  • 你的那个scan_MatrixKey里面是否有延时这类操作的
    • 发布于2019-02-28
    • 举报
    • 评论 0
    • 0
    • 0

  • 你延时后你的主程序就停止运行了,停止运行后你的数码管显示程序就不在执行,即便是你的中断检测到了按键,到实际你也看不到。
    • 发布于2019-02-28
    • 举报
    • 评论 0
    • 0
    • 0

  • 按键在定时中断路判断就可以了,通过计数器延时判断
    • 发布于2019-02-28
    • 举报
    • 评论 0
    • 0
    • 0

  • 矩阵键盘是判断按下之后你再延时10毫秒,这样其实不会很耗时间,我用32做过完全没有任何问题。

    • 发布于2019-02-28
    • 举报
    • 评论 0
    • 0
    • 0

  • 按键在中断里进行判断延时不要超过定时器的值
    • 发布于2019-02-28
    • 举报
    • 评论 0
    • 0
    • 0

  • 键盘扫描除了你说的上说的放到主任务里面或者放到定时任务里面,其实还有第三种方法,并且完全可以避免你所说的这些问题,用中断,把矩阵键盘的横向或者竖向四个IO接到一个四输入与门(或者或门),然后逻辑门的输出接到外部中断上,这样完全就是只有在用户按下按键的时候才会触发键盘任务
    • 发布于2019-03-10
    • 举报
    • 评论 0
    • 0
    • 0

  • 矩阵按键是判断你的按下是有一个延时的,根据灵敏度自己调整一下吧,
    • 发布于2019-03-16
    • 举报
    • 评论 0
    • 0
    • 0

相关问题

问题达人换一批

关于51单片机的矩阵键盘扫描的两种方法的困惑,高手解答~