打印

有那位大侠能说说中断扫描键盘和主程序扫描键盘的优缺点

[复制链接]
楼主: jack.king
手机看帖
扫描二维码
随时随地手机跟帖
81
hungrywolf| | 2008-6-3 11:33 | 只看该作者 回帖奖励 |倒序浏览

我做了几个都是用扫描的

用中断的话又要多一个单片机引脚,而且中断之后也一样要扫描,呵呵,跟楼下的高手意见不同,等着泼水

使用特权

评论回复
82
hyg1984| | 2008-6-3 11:43 | 只看该作者

参与一下

我认为像数码管记数显示等,应该在定时器中段中处理比较好,可以不用在主函数中不停的扫描。

像扫描键盘,特别是矩阵键盘的检测,我认为不应在中断中处理,应该独立写成一个函数,然后在主函数中不停的调用,满足条件(按下键)的话就执行处理键。

理由,你用一个中断,相应的就少了一个中断可用;就算在主函数中不停的调用,没有键按下时,才几个指令,占用不了多少CPU的时间,而且在中断中,处理的时间不能超过定时的时间;中断中消抖也不方便。

有人说,在中断中设置标志位,这样的话跟在主函数中不停的判断也就没有多大的区别了。

这个是我写的,请指教
void trach(void)//键盘检测函数
{
     if(temp!=0xf0)            //有按键(先扫描第一行,主函数中有移位
        {                      //下一行的)
            delay();                 //消抖
            temp=temp&0xf0;
            if(temp!=0xf0)         //重新检测
            {
                temp=P3;          //确实有按键
                switch (temp)      //处理键,当然,硬件不同,方法是不
                {                  
                   case 0xee:num=0;break;
                   case 0xde:num=1;break;
                   case 0xbe:num=2;break;
                   case 0x7e:num=3;break;
                   case 0xed:num=4;break;
                   case 0xdd:num=5;break;
                   case 0xbd:num=6;break;
                   case 0x7d:num=7;break;
                   case 0xeb:num=8;break;
                   case 0xdb:num=9;break;
                   case 0xbb:num=10;break;
                   case 0x7b:num=11;break;
                   case 0xe7:num=12;break;
                   case 0xd7:num=13;break;
                   case 0xb7:num=14;break;
                   case 0x77:num=15;break;
                }
            }
        } 
}
void delay(void)//延迟6ms,消抖
{
    uchar i,j;
    for(i=6;i>0;i--)
        for(j=100;j>0;j--);
}

使用特权

评论回复
83
koolean| | 2008-6-3 16:58 | 只看该作者

我个人觉得这得看程序的具体设计功能

如果主循环的最长周期可以控制在一次按键扫描的循环时间内,则可放在主程序中做,否则放在中断中,并存储好按键值,以作处理。按键如果放在中断中扫描,程序段必须尽量的短,以减少中断时间,有时候,中断时间长是一件很恐怖的事情,非常容易使程序出现莫名其妙的问题。

使用特权

评论回复
84
Swd21ic| | 2008-6-3 21:57 | 只看该作者

Re

我觉得中断里做没什么问题.

一个好的逻辑结构,有确定性.相对多一点开销是值得的.这时调试什么都会方便点.

使用特权

评论回复
85
5880527| | 2008-6-4 09:15 | 只看该作者

83楼的那程序放哪里扫描都不是很好

使用特权

评论回复
86
xwj| | 2008-6-4 09:21 | 只看该作者

唉,误导新人啊...

根本就没入门,还敢充专家说什么“没有多大的区别”...

使用特权

评论回复
87
5880527| | 2008-6-4 09:40 | 只看该作者

这么长一个延时我还真不知道怎么计算出来的

一字我会写,二也会写,可这个万字你想累死我呀

使用特权

评论回复
88
panying180| | 2008-6-7 09:54 | 只看该作者

中断里扫不好

一般扫键会占用几十条指令的时间,而中断的时间是很宝贵的.
扫键的时间要求不会很严格.
可以在中断里置允许扫键的标志位,主程序里根据这个标志位扫键.

使用特权

评论回复
89
西安周公| | 2008-6-10 19:30 | 只看该作者

PC方案可以参考:

使用特权

评论回复
90
新好男孩| | 2008-6-10 21:26 | 只看该作者

喜欢在中断中扫描

我的按键扫描比较简单.但思路很清晰;
/*-------------------------------------------------------*-

    key.H (V1.0)

-*-------------------------------------------------------*/

/*
 * Copyright (c) 2006,
 * All rights reserved
 * 
 * 文件名称: key.h
 * 文件标识: 
 * 摘     要: 
 * 
 * 当前版本: V1.0             * 取代版本:
 * 作     者: wsl         * 修     改:  
 * 版本信息: 2006-12-16         * 修改信息: 
 */ 

//********************************************************

#ifndef    _key_H_
#define    _key_H_

/*定义键值*/
typedef enum {
    K_Set  = 0x00,
    K_Right,
    K_Up,   
    K_Enter
};



// 公用函数
extern void KeyPad(void);

#endif 

//******************end of file***************************

/*--------------------------------------------------------------------*-

    key.C (V1.00)

     
-*---------------------------------------------------------------------*/
/*
 * Copyright (c) 2006,wsl
 * All rights reserved
 * 
 * 文件名称: key.C 
 * 功能描述: 
 * 其它说明: 
 * 
 * 当前版本: V1.0                * 取代版本:
 * 作     者: wsl             * 修     改:  
 * 版本信息: 2006-12-16         * 修改信息: :
 */
//***********************************************************************

#include "main.h"
#include"Port.h"
#include "key.h"
#include "message.h"
//----------------------------------------------------------------------
// 定义键盘扫描程序返回数据类型
typedef struct{
    unsigned char FunctionValue;    // 存放最后扫描到的功能键键值
    unsigned char FunctionCnt;        // 统计功能键的个数
}keyret;

// 按键年龄上限
#define KEYAGE            (2)            // 2~10都可以

//----------------------------------------------------------------------
// 私有函数
static void KeyPadScan(keyret *pKey);

//-----------------------------------------------------------------------
// 存放上次功能键和引导档的键值
        
static unsigned char FunctionKeyBuffer;
static unsigned char KeyAge;                // 按键年龄计数器
static bit bKeyESC;                            // 按键释放标志: 为 0 时已释放    




/*---------------------------------------------------------*-
 * 函数名称: KeyPad()
 * 参    数: 
 * 返    回:
 * 函数功能: 按键处理
 * 
 * 说     明: 
 *
 * 当前版本: V1.0                * 取代版本:
 * 作     者: wsl             * 修     改:  
 * 版本信息: 2006-12-16         * 修改信息:  
-*---------------------------------------------------------*/
void KeyPad(void)
{
    keyret keytemp = {0xff, 0xff};    // 按键无效值
    KeyPadScan(&keytemp);            // 扫描按键
    // 若无功能键按下或多于一个功能键按下,程序将作按键无效处理
    if ( (0xff == keytemp.FunctionCnt) || (keytemp.FunctionCnt > 0x01) )
    {                    
        FunctionKeyBuffer = 0;        // 上次功能键缓冲区清"0"
        KeyAge = 0;                    // 按键年龄计数器清"0"
        bKeyESC = 0;                // 清按键释放标志
        return;
    }
        
    // 若是上次按键末释放则返回
    if (bKeyESC)
        return;
        
    // 若本次功能键/引导键不同,则用本次键值更新上次键值
    if ( FunctionKeyBuffer != keytemp.FunctionValue )
    {
        FunctionKeyBuffer = keytemp.FunctionValue;
        KeyAge = 0;                                    // 按键年龄计数器清"0"
    }
    
    KeyAge++;    // 按键年龄加1

    if ( KeyAge == KEYAGE )
    {    // 确定按键按下
        KeyAge = 0;                                    // 置位按键年龄计数器
        bKeyESC = 1;                                // 置位bKeyESC标志,等待按键释放
        msg_send_msg(MSG_KEY, FunctionKeyBuffer);    // 发送按键消息及键值
    }
}



/*---------------------------------------------------------*-
 * 函数名称: KeyPadScan()
 * 参    数: 
 * 返    回:
 * 函数功能: 按键扫描
 * 
 * 说     明: 扫描引导键/功能键键值及个数 
 *
 * 当前版本: V1.0                * 取代版本:
 * 作     者: wsl             * 修     改:  
 * 版本信息: 2006-12-16         * 修改信息:  
-*---------------------------------------------------------*/
void KeyPadScan(keyret *pKey)
{    
    RL0 = 1;
    RC0 = 1;
    if (!RL0)
    {
        pKey->FunctionCnt++;
        pKey->FunctionValue = K_Set;    
    }

    if (!RC0)
    {
        pKey->FunctionCnt++;
        pKey->FunctionValue = K_Right;
    }

    RL0 = 1;
    RC0 = 0;    
    if (!RL0)
    {
        pKey->FunctionCnt++;
        pKey->FunctionValue = K_Up;
    }

    RL0 = 0;
    RC0 = 1;
    if (!RC0)
    {
        pKey->FunctionCnt++;
        pKey->FunctionValue = K_Enter;
    }

    RL0 = 1;
    RC0 = 1;
}

使用特权

评论回复
91
mikezhong| | 2008-6-11 00:26 | 只看该作者

说说.

一般的消费品产品,主程序中死延时10MS也没有什么大不了,很多项目也是这样做的....

复杂点的,..加中断....

数码管在中断中扫...方便...

使用特权

评论回复
92
jack.king|  楼主 | 2008-6-11 08:30 | 只看该作者

数码管要看什么接法吧

有些数码管可以只要刷新下就好有些接法好象必须不停的刷新,因为在显示LED的时候影响了它

使用特权

评论回复
93
jlgcumt| | 2011-12-18 15:20 | 只看该作者
mark

使用特权

评论回复
94
缥缈九哥| | 2011-12-19 09:19 | 只看该作者
中断及时,主程序不及时 。

使用特权

评论回复
95
缥缈九哥| | 2011-12-19 09:21 | 只看该作者
中断相当于宏观并行操作,能打断主程序先处理键盘;而且主程序在忙时,扫描不了键盘,某些处理会产生按键不灵,迟钝或者丢失的情况 。

使用特权

评论回复
96
lwslws201| | 2011-12-19 09:22 | 只看该作者
:(,还没有做过项目呀!

使用特权

评论回复
97
DownCloud| | 2011-12-19 11:43 | 只看该作者
必需看情况决定吧。这个又没前提条件。
我是尽量放在主程序,实在不行就放中断。
不过放主程序应该就来得及,按键是一百毫秒的事情,连个按键都响应不了的主程序就太悲催了。

使用特权

评论回复
98
MichaelZhouC| | 2015-6-23 23:08 | 只看该作者
这两种分别对CPU有何影响?以及各自的响应速度?

使用特权

评论回复
99
qduwg| | 2015-6-24 12:35 | 只看该作者
machunshui 发表于 2008-5-20 11:39
定时中断里面计数,到时间置一个键盘处理的事件标志,有标志,主循环就做键盘扫描,作完毕,事件标志归0, ...

这个方法不错的。思路清晰可用。感谢

使用特权

评论回复
100
anazel| | 2016-2-25 11:38 | 只看该作者
DownCloud 发表于 2011-12-19 11:43
必需看情况决定吧。这个又没前提条件。
我是尽量放在主程序,实在不行就放中断。
不过放主程序应该就来得及 ...

我就是把扫描键盘程序放在主函数中,因为LCD显示的东西多,所以按键非常不灵敏,需要在主程序中多次调用键盘扫描程序。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则