打印
[51单片机]

一个按键两种功能,短按一个功能,长按一个功能.

[复制链接]
18897|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
caixiaojung|  楼主 | 2014-4-27 22:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚学51一个月,学生想找个老师点拔一下谢谢了,想写一个按键两种功能,就是短按一下LED灯亮,再按一下灭,长按2秒另一个LED亮,再按一下灭,想了好久写不出来,下面是学生写的不完整程序#include<reg52.h>
#define uint unsigned int
sbit led1=P1^0;
sbit led2=P1^1;
sbit key1=P3^4;
void delay(uint xms)
{
        uint i,j;
        for(i=xms;i>0;i--)
        for(j=110;j>0;j--);
}
void main()
{
        while(1)
        {
                if(key1==0)
                {
                        delay(10);
                        if(key1==0)
                        {
                                led1=~led1;
                                while(!key1);
                        }
                }
        }       
}

相关帖子

沙发
coody| | 2014-4-27 22:24 | 只看该作者
监控按下时间,短按是释放执行,长按是到时间执行

使用特权

评论回复
板凳
swustlx86| | 2014-4-28 08:39 | 只看该作者
楼主可以参考下这个帖子  http://www.amobbs.com/forum.php? ... =%E6%8C%89%E9%94%AE

使用特权

评论回复
地板
限量_个性。| | 2014-4-28 09:56 | 只看该作者
写成按键状态机的形式吧。

使用特权

评论回复
5
天风立马| | 2014-4-28 12:36 | 只看该作者
412809312加我Q,我给你个代码,你看看.或者我给你说说.呵呵

使用特权

评论回复
6
天风立马| | 2014-4-28 12:39 | 只看该作者
用延时消抖我认为是自欺欺人.哈哈.

使用特权

评论回复
7
sdwflzg| | 2014-4-29 10:27 | 只看该作者
我给你来个试试(已调试)
/*******************************************************
|一个按键两种功能,就是短按一下LED灯亮,
|再按一下灭,长按2秒另一个LED亮,再按一下灭
|
*******************************************************/
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int //宏定义:unit=unsigned int
#define uchar unsigned char

sbit led1=P1^0;
sbit led2=P1^1;

sbit s=P3^5;

uchar flag1,flag2;

void delay(uint);
void keyscan();

void main()
{
        while(1)
        {
                keyscan();

        }
}
void keyscan()
{
        uint j;
        j=0;
        s=1;
        if(flag1==1||flag2==1)
        {       
                if(!s)
                {
                        delay(5);
                        if(!s)
                        {
                                while(!s);
                                flag1=0;
                                flag2=0;
                                led1=1;
                                led2=1;
                        }
                }
        }
        else
        {
                if(!s)
                {
                        delay(5);
                        if(!s)
                        {
                                while(s==0 && j<30000)
                                {
                                //        delay(5);
                                        j++;
                                }
       
                                        if (j>=30000)
                                        {
                                                flag2=1;
                                                led2=0;
                                                while(!s);       
                                        }
                                        else
                                        {
                                                flag1=1;
                                                led1=0;
                                        }
                               
                                       
                        }
                }
        }       
}
void delay(uint z)
{
        //1ms延时
        uint i,j;
        for(i=z;i>0;i--)
                for(j=110;j>0;j--);
}

使用特权

评论回复
8
huangxz| | 2014-4-29 10:43 | 只看该作者
2#正解,一般这个都是状态机形式的

使用特权

评论回复
9
caixiaojung|  楼主 | 2014-4-29 18:56 | 只看该作者
谢谢sdwflzg,终于看明白怎么写了,太感谢了!以后有不懂的还要劳烦你了,非常感谢,我被这个程序困好几天了,睡都睡不着,现在感觉比中大奖都高兴,现在迷上单片机了,没办法啊.

使用特权

评论回复
10
sdwflzg| | 2014-4-29 19:37 | 只看该作者
caixiaojung 发表于 2014-4-29 18:56
谢谢sdwflzg,终于看明白怎么写了,太感谢了!以后有不懂的还要劳烦你了,非常感谢,我被这个程序困好几天了,睡 ...

我也是刚上手,一起研究。:handshake

使用特权

评论回复
11
caixiaojung|  楼主 | 2014-5-1 11:01 | 只看该作者
sdwflzg 发表于 2014-4-29 10:27
我给你来个试试(已调试)
/*******************************************************
|一个按键两种功能, ...

如果上面的延时全部用定时器来延时那怎么写呢,是不是很麻烦

使用特权

评论回复
12
ZG11211| | 2014-5-2 17:44 | 只看该作者
本帖最后由 ZG11211 于 2014-5-2 17:46 编辑

定时扫描按键,如果有按键按下,开始计数。否则,判断计数值,少于i 视为抖动或没有按下按键,i<j<K视为短按,>k视为长按,执行相应操作,最后清计数值。

使用特权

评论回复
13
flame123| | 2014-5-3 12:05 | 只看该作者
楼主还是看状态机吧,现在可能会麻烦点,以后会很爽,不要为了实现功能而去实现功能。

使用特权

评论回复
14
sfesdm| | 2014-5-3 12:17 | 只看该作者
说句实话,不是打击7楼,如果按照那种思路写,会害死你自己,毕业后参加工作就知道了。还是先学好定时器中断吧,然后用定时器来实现

使用特权

评论回复
15
sdwflzg| | 2014-6-6 09:02 | 只看该作者
sfesdm 发表于 2014-5-3 12:17
说句实话,不是打击7楼,如果按照那种思路写,会害死你自己,毕业后参加工作就知道了。还是先学好定时器中 ...

谢谢老师指导,用什么方式你要看你用单片机干什么,是吧!

使用特权

评论回复
16
向上的小树| | 2015-8-4 10:57 | 只看该作者
coody 发表于 2014-4-27 22:24
监控按下时间,短按是释放执行,长按是到时间执行

非常感谢,用您说的方法我才实现了长按与短按的功能,没有用到延时,用定时器每隔一段时间来判断按键状态,并进行计数或者执行短按操作。一开始按照12楼的思路来写程序,一直写不出来,后来照着您的思路来,终于写出来了。再次感谢,我用的是读取按键扫描程序的值,这样的话就必须要按键扫描程序支持连按才可以。也许直接判断按键状态会更好些。

使用特权

评论回复
17
coody| | 2015-8-5 22:05 | 只看该作者
按键是慢速事件,用定时器扫描就很好。

使用特权

评论回复
18
delin17| | 2015-8-6 16:49 | 只看该作者

void KeyScan()
{
        static UINT32 u32Debounce=0;
        static UINT32 u32KeyFlag=0;
        UINT32 u32OldKeyRelease;
        static UINT32 u32LastKey=(KEY_IOI_MASK<<14)|(KEY_IOA_MASK>>1)|(0x03<<24)|(0x03<<26);
        UINT32 u32KeyTmp = (~GetAllKeys())&KEY_MASK;
        u32OldKeyRelease = ~DetectOldKeys_New2(g_u32KeyCode);
        //u32OldKeyRelease= ~DetectOldKeys(g_u32KeyCode);
        u32KeyTmp&=u32OldKeyRelease;
        g_u32KeyCode &=        u32OldKeyRelease;
   
        if(u32KeyTmp !=u32LastKey)
        {
                /*if(u32KeyFlag ==1)
                {
                        g_u32KeyCode =u32LastKey;
                }*/
                u32KeyFlag =1;
                u32Debounce=0;
                u32LastKey = u32KeyTmp;
               
        }
        else if(u32KeyFlag==1)
        {
                u32Debounce++;
                if(C_DEBOUNCE <=u32Debounce)
                {
                        u32Debounce = C_DEBOUNCE+1;
                        u32KeyFlag=2;
                        g_u32KeyCode = u32KeyTmp;

                }
        }       
}
简单的示例,长按,短按,你再联想一下就知道了

使用特权

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

本版积分规则

2

主题

5

帖子

0

粉丝