[讨论] 扫描和中断思想

luchao114   2009-5-15 12:12 楼主
由于每次键盘扫描都会浪费10ms的时间,所以,我想用中断(将按键的各行通过与门连接到中断口0上),但是怎样可以设计出既可以让CPU不去扫描按键,又能正确的处理按键按下时的程序呢?

回复评论 (8)

定时器如果有富余,可以用定时器中断去触发扫描键盘。

由于人用手去按按键的最快速度也要40mS,一般不是特意快速按按键的话往往要100mS以上,为了不漏掉有效的按键,可用60mS中断去触发扫描按键(60mS对应12M晶振时的定时器方式1约最长定时时间,也可用65.536mS),在中断程序中先是查有没有按键按下,如果没有,立即退出定时器中断,这并不怎么影响系统的效率,否则,检查到有按键按下的话,可根据你系统实际情况,既可以给出标志然后推出中断到主程序中继续扫描按键并判断键值,也可以直接在定时器中继续扫描按键并判断键值。
点赞  2009-5-15 12:31

用状态机

比方做一个1~数ms的定时器中断对单片机来说几乎没什么负担,每次进入中断服务程序读一次键就退出。当连续读得同样键值的次数达到某个设定值时,就认为该键真的是被按下了。
点赞  2009-5-15 12:37

回复 板凳 仙猫 的帖子

你的思想不错,但我试过了,结果有这样的问题:我想“连续读得同样键值的次数达到某个设定值”,肯定要定义一个全局变量,它的值是不会丢失的。假如这样:正常按下是需要60ms,假定设置20ms中断一次。如果出现20ms的干扰2次,全局变量则计为2,如果再次出现,那么全局变量为3,即为60ms,产生中断,实际还是20ms,所以如何对这种干扰计数的全局变量的值清除呢?这个怎么考虑呢?
点赞  2009-5-15 17:19

回复 4楼 luchao114 的帖子

在子程序调用返回的时候清零就好!
我的邮箱gaoxiaoan123@163.com!回帖是一种美德!互相帮助,共同进步! 口头禅:生活在于创造机会,把握机会!
点赞  2009-5-15 19:03

按键超过60ms才反应是否会有迟钝感呢?

引用: 原帖由 luchao114 于 2009-5-15 17:19 发表
你的思想不错,但我试过了,结果有这样的问题:我想“连续读得同样键值的次数达到某个设定值”,肯定要定义一个全局变量,它的值是不会丢失的。假如这样:正常按下是需要60ms,假定设置20ms中断一次。如果出现20ms的 ...

我通常是这么做的,看能否供LZ参考:
1、定义1ms定时中断。(1ms仅是为了易算,慢速CPU的话可把周期改长,如5ms。下面以1ms中断为例,键值连续8ms相同则予以承认。)
2、静态局部变量:计数器cnt、上次键值cur;另置一全局flg作为按键标志对外发布。
3、进入中断后读键,若=cur,cnt不满7则加1,满7时承认该键值;若键值=cur则cnt清零,并把当前键值赋给cur(更新)。

用以上做法,如再仔细考虑一下键值发布的方式,也能很容易地做到像PC键盘那样的对长按键的连续处理:长按键时,开始是800ms后作第2次输出,以后每隔80ms输出一次。
点赞  2009-5-15 22:19
恩,谢谢你,如果你身边有键盘程序能给我参考究更好了。
点赞  2009-5-15 22:33
古董是有的,不一定用得上,贴上试试,如有用最好。

#define KEY_DET_TM  10    /* 按键去抖动时间(ms) */
#define FIRST_RPT   500    /* 初次重复键的间隔(ms) */
#define CONT_RPT    80      /* 第2次以后的连续键间隔(ms) */

void Int_SysTimer(void)       /* 1ms间隔的中断服务程序 */
{
    static unsigned short  cnt_Key, new_Key;

    if (new_Key && (new_Key == KeyIn())) {
        if (++cnt_Key == KEY_DET_TM) {
            Ctrl.key = new_Key;
        } else if (cnt_Key >= (KEY_DET_TM + FIRST_RPT + CONT_RPT)) {
            cnt_Key = (KEY_DET_TM + FIRST_RPT);
            Ctrl.key = new_Key;
        } else if (cnt_Key == (KEY_DET_TM + FIRST_RPT)) {
            Ctrl.key = new_Key;
        }
    } else if (KeyIn() != new_Key) {
        new_Key = KeyIn();
        cnt_Key = 0;
    }
}
点赞  2009-5-15 23:19
非常谢谢你!
点赞  2009-5-16 09:48
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复