打印
[51单片机]

简单的用定时器进行按键消抖,写得不好,望大家指点!

[复制链接]
3411|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
/********************************
        按独立按键使数码管加1
********************************/
#include <reg52.h>

#define uchar unsigned char

sbit KEY = P1 ^ 0;                                                                                         //定义独立按键
bit KEYSTA = 1;                                                                                         //按键的初始状态
uchar code DispCode[] = {0xc0,0xf9,0xa4,0xb0,                                 //共阳数码管
                          0x99,0x92,0x82,0xf8,
                          0x80,0x90,0x88,0x83,
                          0xc6,0xa1,0x86,0x8e};
void Timer0Init();                                                                                        //定时器初始化函数
void KeyProcess();                                                                                        //按键处理函数

void main()
{
        Timer0Init();
        KeyProcess();
}

void Timer0Init()
{
        TMOD |= 0x01;
        TH0 = 0xF8;                          //定时2MS
        TL0 = 0xCD;
        EA =1;
        ET0 = 1;
        TR0 = 1;
}
void KeyProcess()
{
        bit lasttime = 1;                                                 //定义前一次按键值,初始化为1;
        uchar count = 0;                                                 //计数值初始化为0;
        KEY = 0x01;                                                                 //按键初始化;
        P0 =  DispCode[count];                                         //数码管初始化;
        while(1)
        {
                if (KEYSTA != lasttime)                                 //如果“当前按键状态”与“前一次按键状态”不同,说明按键有动作;
                {
                        if (lasttime == 1)                                 //如果按键有动作了,那么前一次按键状态为“弹起”(lasttime == 1),说明按键按下时,会响应动作;
                        {
                                count++;
                                if (count >= 16)                         //计数加到16清零,只用一个共阳数码管;
                                {
                                        count = 0;
                                }
                                P0 =  DispCode[count];                 //共阳数码管显示相应的值;
                        }
                        lasttime = KEYSTA;                                 //如果按键有动作,就更新前一次按键的值;
                }
        }
}

void Timer0IRQ() interrupt 1                                //2MS中断一次
{
        static keybuf = 0xFF;                                        //定义一个静态按键缓存变量,且值为FF;主要是暂存按键状态;
        TH0 = 0xF8;                                            //重新写入初值;
        TL0 = 0xCD;
       
        keybuf = (keybuf << 1) | KEY;                    //左移一位,使当前的按键状态移到按键缓存中;
        if (keybuf == 0)                                                //如果移8次,按键状态都为0,说明按键真正按下;
        {
                KEYSTA = 0;                                                    //确定按键状态为按键;
        }
        else if (keybuf == 0xFF)                                //如果移8次,按键状态都为1,说明按键未按下
        {
                KEYSTA = 1;
        }
}


相关帖子

沙发
ayb_ice| | 2016-8-5 08:13 | 只看该作者
思路比较新颖,最后状态标志被主循环使用要考虑互斥问题,

使用特权

评论回复
板凳
小分子|  楼主 | 2016-8-5 13:40 | 只看该作者
ayb_ice 发表于 2016-8-5 08:13
思路比较新颖,最后状态标志被主循环使用要考虑互斥问题,

大神啊。能讲得通俗易懂点吗?我自学的,想让程序更接近实际项目,你就费心给指点一二吧。

使用特权

评论回复
地板
shisizai| | 2016-8-5 14:39 | 只看该作者
感觉有点麻烦……
你觉得 移位 比 延时要好么?

使用特权

评论回复
5
小分子|  楼主 | 2016-8-5 15:58 | 只看该作者
shisizai 发表于 2016-8-5 14:39
感觉有点麻烦……
你觉得 移位 比 延时要好么?

延时,还要等待按键释放。我这个用的是中断。

使用特权

评论回复
6
shisizai| | 2016-8-5 16:27 | 只看该作者
小分子 发表于 2016-8-5 15:58
延时,还要等待按键释放。我这个用的是中断。

从按键按下的时候开始延时,如果超过t按键仍然按下则认为实际按下
需要松手检测的话再在后面直接加个while就行了

你程序里的思想有点像状态机,我觉得用c的话越简单越好,中断还是留给更重要的地方吧

使用特权

评论回复
7
小分子|  楼主 | 2016-8-5 16:48 | 只看该作者
shisizai 发表于 2016-8-5 16:27
从按键按下的时候开始延时,如果超过t按键仍然按下则认为实际按下
需要松手检测的话再在后面直接加个whil ...

不用中断。delay()这个延时也不准,如果程序小可以,若是程序大一点,CPU不就满负荷了吗?

使用特权

评论回复
8
shisizai| | 2016-8-5 16:58 | 只看该作者
小分子 发表于 2016-8-5 16:48
不用中断。delay()这个延时也不准,如果程序小可以,若是程序大一点,CPU不就满负荷了吗? ...

直接对晶振分频 延时精度一般够用了。追求准确的话外加时钟芯片,定时器啥的都行。
大程序的话……你在中断里判断按下的时间长度cpu就放松了么……不了解
另外你的程序中一个key一个数值,要是有8个独立按键呢,要是一个矩阵键盘呢 程序复杂度就高了啊

使用特权

评论回复
9
小分子|  楼主 | 2016-8-7 07:54 | 只看该作者
shisizai 发表于 2016-8-5 16:58
直接对晶振分频 延时精度一般够用了。追求准确的话外加时钟芯片,定时器啥的都行。
大程序的话……你在中 ...

我也想这里了。如果是4X4那程序是很麻烦的。你能给一个矩阵键盘扫描的程序不?

使用特权

评论回复
10
shisizai| | 2016-8-10 14:20 | 只看该作者
小分子 发表于 2016-8-7 07:54
我也想这里了。如果是4X4那程序是很麻烦的。你能给一个矩阵键盘扫描的程序不? ...

uchar Keyscan(void)
{
        uchar i,j, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};                        //让矩阵键盘的每行分别为低电平
        for(j=0; j<4; j++)
        {
                P1 = Buffer[j];
                temp = 0x10;                                                                                                                                                                 
                for(i=0; i<4; i++)
                {
                        if(!(P1 & temp))                 //判断P1口高4位某一行为低电平
                        {
                                return (i+j*4);                //返回键码
                        }
                        temp <<= 1;
                }       
        }
}

捕获.PNG (42.7 KB )

捕获.PNG

使用特权

评论回复
11
小分子|  楼主 | 2016-8-10 21:48 | 只看该作者
shisizai 发表于 2016-8-10 14:20
uchar Keyscan(void)
{
        uchar i,j, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};                        //让矩阵键盘的每行 ...

谢谢你。辛苦了。

使用特权

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

本版积分规则

18

主题

68

帖子

1

粉丝