找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 23884|回复: 38
收起左侧

非常稳定可靠的单片机按键消抖程序,绝对不会产生抖动

  [复制链接]
ID:114701 发表于 2018-5-22 09:15 | 显示全部楼层 |阅读模式
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit K1 = P1^0;
void delay1ms(uint n)  
{
    uchar  a,b,c,d;
for(d=n;d>0;d--)
    for(c=1;c>0;c--)
        for(b=222;b>0;b--)
            for(a=12;a>0;a--);
}
void main()
{
    uint i;
        if(K1==0)
        {
                delay1ms(10);  
                if(K1==0)    //
                {
                        for(i=0;i<100;i++)     //此处消抖程序非常经典,怎么按都绝对不会产生抖动。
                        {
                        if(K1==0)
                           i=0;
                        }
                在这儿添加按键按下后要执行的功能。
                }
        }
}

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:313328 发表于 2018-10-29 18:32 | 显示全部楼层
非常可以
回复

使用道具 举报

ID:66287 发表于 2018-10-30 15:34 | 显示全部楼层
if(K1==0)    //
                {
                        for(i=0;i<100;i++)     //此处消抖程序非常经典,怎么按都绝对不会产生抖动。
                        {
                        if(K1==0)
                           i=0;
                        }
                在这儿添加按键按下后要执行的功能。
                }
比较巧妙!
回复

使用道具 举报

ID:66287 发表于 2018-10-30 15:58 | 显示全部楼层
说白了就是放手执行动作,但延时消抖有些傻傻的,期间什么也干不了。
回复

使用道具 举报

ID:66287 发表于 2018-10-30 16:02 | 显示全部楼层
//非常稳定可靠的单片机按键消抖程序,绝对不会产生抖动
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit K1 = P1^4;
sbit K2 = P1^5;
void delay1ms(uint n)  
{
    uchar  a,b,c,d;
for(d=n;d>0;d--)
    for(c=1;c>0;c--)
        for(b=222;b>0;b--)
            for(a=12;a>0;a--);
}
void main()
{
    uint i;
        if(K1==0)
        {
                delay1ms(10);  
                if(K1==0)    //
                {
                        for(i=0;i<100;i++)     //此处消抖程序非常经典,怎么按都绝对不会产生抖动。
                        {
                        if(K1==0)
                           i=0;
                        }


        P0=P0|0x01;     //左移后,最右端自动赋值0,所以需要该语句赋值1
        P0<<=1;
                }
        }
                if(K2==0)
        {
                delay1ms(10);  
                if(K2==0)    //
                {
                        for(i=0;i<100;i++)     //此处消抖程序非常经典,怎么按都绝对不会产生抖动。
                        {
                        if(K2==0)
                           i=0;
                        }



        P0 = 0xff;
                }
        }
}


1.png
回复

使用道具 举报

ID:399179 发表于 2018-10-30 19:11 来自手机 | 显示全部楼层
感谢楼主分享!
回复

使用道具 举报

ID:419063 发表于 2018-11-1 13:41 | 显示全部楼层
有点儿意思!
回复

使用道具 举报

ID:84765 发表于 2018-11-5 17:26 | 显示全部楼层
学习了!
回复

使用道具 举报

ID:387856 发表于 2018-12-15 20:17 | 显示全部楼层
bhjyqjs 发表于 2018-10-30 15:58
说白了就是放手执行动作,但延时消抖有些傻傻的,期间什么也干不了。

兄弟 你不能这么想,按照这位楼主的思路,可以搞成不用傻傻的等啊,利用定时器中断不就行了吗   是不是
回复

使用道具 举报

ID:444306 发表于 2018-12-16 01:32 | 显示全部楼层
加油!抓住每一次灵感,活的当下才精彩!
回复

使用道具 举报

ID:416139 发表于 2018-12-16 11:00 | 显示全部楼层
应该再放一个松手检测
回复

使用道具 举报

ID:583312 发表于 2019-7-20 09:48 | 显示全部楼层
bhjyqjs 发表于 2018-10-30 15:34
if(K1==0)    //
                {
                        for(i=0;i

太巧秒了
回复

使用道具 举报

ID:515684 发表于 2019-7-20 14:25 | 显示全部楼层
还没学到这么高级,有需要时借鉴借鉴。谢谢分享。
回复

使用道具 举报

ID:137005 发表于 2019-7-20 17:36 | 显示全部楼层
学习学习,谢谢分享!
回复

使用道具 举报

ID:483407 发表于 2019-7-20 22:45 | 显示全部楼层
请问此处的FOR循环,与前面的延时10毫秒有什么区别?
回复

使用道具 举报

ID:282726 发表于 2019-8-10 08:32 | 显示全部楼层
前面检测的是按下
后面检测的松开
回复

使用道具 举报

ID:496061 发表于 2019-8-14 16:19 | 显示全部楼层
怎么感觉很多此一举,小白不是很懂,在第一次按键按下后还是用了延时进行了一次消抖,后面还再来一次消抖的意义在哪里?请各位大佬指点
回复

使用道具 举报

ID:71883 发表于 2019-9-30 16:49 | 显示全部楼层
楼主我今天试了一下加了关键一句按键无法循环,无法做自锁按键,再说你的按下检测,没有松手检测。
回复

使用道具 举报

ID:59909 发表于 2019-11-11 17:13 | 显示全部楼层
bhjyqjs 发表于 2018-10-30 15:58
说白了就是放手执行动作,但延时消抖有些傻傻的,期间什么也干不了。

对头!!一语道破!
回复

使用道具 举报

ID:156923 发表于 2019-11-26 09:58 | 显示全部楼层
#include "Key.h"



u16 Key_Lock;                        //按键锁定
u16 Key_Down;                        //按键被按下
u16 Key_Up;                          //按键释放
u16 Key_Count[16];                    //消抖计数


//消抖次数
code u16 Key_Threshold[] =
{
100,            //0x0001
100,            //0x0002
1,            //0x0004
1,            //0x0008
1,            //0x0010
1,            //0x0020
1,            //0x0040
1,            //0x0080
1,            //0x0100
1,            //0x0200
1,            //0x0400
1,            //0x0800
1,            //0x1000
1,            //0x2000
1,            //0x4000
1            //0x8000
};


/*========================================================
//触摸按键检测  主程序 长调用
//
=========================================================*/
void Key_Scan()
{
    u8 i;
    u16 Loop_Bit = 1;
    u16 Key = 0;

    if(K1_IO == 0)
    {
        Key |= 0x01;
    }

    if(K2_IO == 0)
    {
        Key |= 0x02;
    }

    for(i = 0; i < 16; i++)
    {
        if((Key_Lock & Loop_Bit) == 0)         //如果按键未锁定
        {
            if(Key & Loop_Bit)         //如果按键被按下,把相应位置位
            {
                Key_Count[i]++;
                if(Key_Count[i] >= Key_Threshold[i])
                {
                    Key_Count[i] = 0;
                    Key_Lock |= Loop_Bit;       //锁定按键
                    Key_Down |= Loop_Bit;       //触发按键   
                }
            }
            else
            {
                Key_Count[i] = 0;
            }
        }
        else                                      //如果按键被锁定
        {
            if((Key & Loop_Bit) == 0)  //如果按键被释放,把相应为清零
            {
                Key_Count[i]++;
                if(Key_Count[i] >= Key_Threshold[i])
                {
                    Key_Count[i] = 0;
                    Key_Lock &= ~Loop_Bit;
                    Key_Up |= Loop_Bit;  
                }
            }
            else
            {
                Key_Count[i] = 0;
            }
        }
        Loop_Bit <<= 1;
    }
}


/*
10毫秒调用一次
*/
void Key_Handle()
{  
    //组合按键
    if((Key_Lock & (KEY1 | KEY2)) == (KEY1 | KEY2))
    {
    }

    //任意按键按下
    if(Key_Down)
    {
    }

    //按键按下触发--
    if(Key_Down & KEY1)
    {
        Key_Down &= ~KEY1;
    }
    //按键释放触发
    if(Key_Up & KEY1)
    {
        Key_Up &= ~KEY1;
    }


    //按键按下触发--
    if(Key_Down & KEY2)
    {
        Key_Down &= ~KEY2;
    }
    //按键释放触发
    if(Key_Up & KEY2)
    {
        Key_Up &= ~KEY2;
    }

    //按键按下触发--
    if(Key_Down & KEY3)
    {
        Key_Down &= ~KEY3;
    }
    //按键释放触发
    if(Key_Up & KEY3)
    {
        Key_Up &= ~KEY3;
    }

    //按键按下触发--
    if(Key_Down & KEY4)
    {
        Key_Down &= ~KEY4;
    }
    //按键释放触发--
    if(Key_Up & KEY4)
    {
        Key_Up &= ~KEY4;
    }


}
回复

使用道具 举报

ID:491577 发表于 2019-11-27 19:28 | 显示全部楼层
消抖程序已经淘汰了,根本就不需要消抖,把按键检测程序放到间隔10ms以上的中断中,按键抖动小于10ms,间隔10ms以上的中断意味着抖动期间最多只会检测到一次,无论检测到0还是1都不影响结果。所以根本就不需要消抖,也不需要按键释放。按键释放程序会影响数码管显示,一按键数码管显示就停止了。
回复

使用道具 举报

ID:235332 发表于 2019-12-25 15:58 | 显示全部楼层
非常傻的一种消抖方式,建议不要用,延时消抖,期间什么都干不了
回复

使用道具 举报

ID:395068 发表于 2019-12-28 14:03 | 显示全部楼层
用定时器中断消抖比较好
回复

使用道具 举报

ID:65956 发表于 2020-1-20 14:20 | 显示全部楼层
很有意思,很有值的学习的地方,下次项目可以试看看如何
回复

使用道具 举报

ID:687607 发表于 2020-1-20 18:50 来自手机 | 显示全部楼层
来学习学习
回复

使用道具 举报

ID:142059 发表于 2020-1-22 06:58 来自手机 | 显示全部楼层
不放手是执行不了的,你的思路很对,但是还有改进的地方
回复

使用道具 举报

ID:604793 发表于 2020-4-15 11:12 | 显示全部楼层
hhh402 发表于 2019-11-27 19:28
消抖程序已经淘汰了,根本就不需要消抖,把按键检测程序放到间隔10ms以上的中断中,按键抖动小于10ms,间隔 ...

会检测错误吧,假如没有按下,中断的时候检测到了一次抖动是按下的,不就错误了嘛,还得用统计的方法吧
回复

使用道具 举报

ID:619259 发表于 2020-4-15 16:37 | 显示全部楼层
玩玩可以,没多大意思。
回复

使用道具 举报

ID:777834 发表于 2020-9-7 22:26 来自手机 | 显示全部楼层
rebios 发表于 2019-8-10 08:32
前面检测的是按下
后面检测的松开

怎样检测松开的呢,新手,不是很懂,谢谢
回复

使用道具 举报

ID:378732 发表于 2020-9-8 17:47 | 显示全部楼层
jianuli 发表于 2020-9-7 22:26
怎样检测松开的呢,新手,不是很懂,谢谢

已经是有松手检测了,手不松i=0   for循环出不去。手松开之后经过i从0到100的延时出去执行按下要执行的任务。
回复

使用道具 举报

ID:817950 发表于 2020-9-11 16:02 | 显示全部楼层
太老了,初学者用延时消抖,工程中基本都是按键状态机了,CPU占用资源少10-20ms调用一次就行
回复

使用道具 举报

ID:292876 发表于 2020-9-13 14:46 来自手机 | 显示全部楼层
咋还讨论按键次消抖呢?马师傅按键消抖,吴师傅按键消抖,都是完美的方法,可以添加单触发,多触发,长按等
回复

使用道具 举报

ID:164385 发表于 2020-9-14 17:55 | 显示全部楼层
此时不能做其他事情,其应用会有局限性。
回复

使用道具 举报

ID:928738 发表于 2022-8-18 15:34 | 显示全部楼层
做实验可以,实际应用效果不太好
回复

使用道具 举报

ID:1027834 发表于 2022-8-19 18:26 | 显示全部楼层
确实很经典,如果将延时函数改为状态机方式进行计时的话,我想会使得代码效率更高。
回复

使用道具 举报

ID:34149 发表于 2022-8-20 13:19 | 显示全部楼层
不放手试一试有啥结果没?
回复

使用道具 举报

ID:485350 发表于 2023-4-7 16:44 | 显示全部楼层
hhh402 发表于 2019-11-27 19:28
消抖程序已经淘汰了,根本就不需要消抖,把按键检测程序放到间隔10ms以上的中断中,按键抖动小于10ms,间隔 ...

实际上非常容易二次触发
回复

使用道具 举报

ID:1038987 发表于 2023-4-8 11:29 | 显示全部楼层
liuhailan5757 发表于 2018-12-15 20:17
兄弟 你不能这么想,按照这位楼主的思路,可以搞成不用傻傻的等啊,利用定时器中断不就行了吗   是不是

用电容,并0.1UF电容就可以了
回复

使用道具 举报

ID:1064915 发表于 2023-4-8 14:17 | 显示全部楼层
ziyueboy 发表于 2020-9-13 14:46
咋还讨论按键次消抖呢?马师傅按键消抖,吴师傅按键消抖,都是完美的方法,可以添加单触发,多触发,长按等

把程序贴出来
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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