找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4756|回复: 5
收起左侧

单片机长短按键控制程序

  [复制链接]
ID:237797 发表于 2021-9-11 11:07 | 显示全部楼层 |阅读模式
实际应用中很多地方用到按键长短按键。下面是我写的代码,一是作为我自己笔记在这里,二看有没有朋友有更好的写法。代码如下:
#include"stc15w.h"

#define u8 unsigned char
#define u16 unsigned int

sbit LEDR = P1^0;
sbit LEDG = P1^1;
sbit LEDB = P1^2;
sbit KEY = P0^0;

u16 keyTim; //按键时间
u16 sysTim; //系统时间

u8 keyshort; //短按键标志
u8 keylong;  //长按键标志
u8 LEDON;    //开灯状态
u8 flag1ms;  //1ms标志

void key_Proc(); //按键处理
void led_Proc();  //灯处理
void Timer0Init(); //中断初始化

void main()
{
    LEDR = 0;    //上电灯全灭(上电灯初始化)
    LEDG = 0;
    LEDB = 0;
    Timer0Init();  //中断初始化

    while(1)
    {
        key_Proc();   //按键处理
        led_Proc();  //灯处理
    }

}

void key_Proc()    //按键处理
{
    if(flag1ms)  //1ms时间标志
    {
        flag1ms = 0;
        if(KEY)
        {
            if((keyTim>10)&&(keyTim<500))  //按键时间大于10ms小于50ms,是短按键
            {
                keyshort = 1;   //短按键标志
            }
            keyTim = 0;        //按键时间清零
        }
        else
        {
            if(keyTim<10001)    //按键时间小于10S
            keyTim++;           //按键时间加
            if(keyTim==1000)    //按键时间为1S
            {
                keylong = 1;    //长按键标志
            }
        }      
    }
}

void led_Proc()   //灯处理
{
    static u8 i;

    if((LEDON==0)&&(keylong==1))  //关灯状态同时长按键按下就开灯
    {   
        keylong = 0;  //长按键松开
        LEDON = 1;    //关灯时就开灯
        LEDR = 1;     //RGB灯亮白光
        LEDG = 1;
        LEDB = 1;
    }        
    if((LEDON==1)&&(keylong==1)) //开灯状态同时长按键按下就关灯
    {   
        keylong = 0;  //长按键松开
        LEDON = 0;    //开灯时就关灯
        LEDR = 0;     //RGB灯灭
        LEDG = 0;
        LEDB = 0;
    }

    if((LEDON==1)&&(keyshort==1))  //开灯状态同时短按键按下,亮灯模式切换
    {   
        keyshort = 0;  //短按键松开
        switch(i)
        {
            case 0:LEDR = 1;LEDG = 0;LEDB = 0;break; //红
            case 1:LEDR = 1;LEDG = 1;LEDB = 0;break; //黄
            case 2:LEDR = 0;LEDG = 1;LEDB = 0;break; //绿
            case 3:LEDR = 0;LEDG = 1;LEDB = 1;break; //青
            case 4:LEDR = 0;LEDG = 0;LEDB = 1;break; //蓝
            case 5:LEDR = 1;LEDG = 0;LEDB = 1;break; //紫
            case 6:LEDR = 1;LEDG = 1;LEDB = 1;break; //白                  
        }
        i++;
        i = i%7;  //7次循环切换
    }
}

void Timer0Init()   //中断初始化
{
    AUXR &= 0x7F;   //定时器时钟12T(12分频)模式
    EA = 1;       //开中断
    TMOD &= 0XF0; //中断0模式1
    TMOD |= 0X01;
    TH0 = 0XFC;   //初值1ms
    TL0 = 0X66;
    ET0 = 1;     //允许T0中断
    TR0 = 1;    //定时器0开始计时
}

void interruptTimer0() interrupt 1
{
    TH0 = 0XFC;
    TL0 = 0X66;
    flag1ms = 1; //1ms标志
    sysTim++;  //系统时间
}

评分

参与人数 2黑币 +55 收起 理由
ax6808 + 5 阀值 const_key_time_short1 或者 const_ke.
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:607312 发表于 2021-9-12 10:04 | 显示全部楼层
验证了好像代码不行,。正在调试一下看看行不行
回复

使用道具 举报

ID:237797 发表于 2021-9-13 08:28 | 显示全部楼层
cdiyy 发表于 2021-9-12 10:04
验证了好像代码不行,。正在调试一下看看行不行

我用的STC的单片机,可以的。
回复

使用道具 举报

ID:975054 发表于 2022-11-29 19:15 | 显示全部楼层
    写的很好,很清晰,很难得!必须暂1个!

    长短按时长阀值:可根据实际调整; 看过吴坚鸿老师的教程.
    期间由于受外界干扰或者按键抖动,而使 IO 口突然瞬间触发成高电平,这个时候马上把延时计数器清零了,这个过程非常巧妙,可非常有效地去除瞬间的杂波干扰。这是他实战中摸索出来的。 以后凡是用到开关感应器的时候,都可以用类似这样的方法去干扰。
    如果按键按下的时间超过了短按阀值,则马上把短按标=1;
    如果还没有松手,一旦发现按下的时间超过长按阀值时(个人觉得1-2秒合适了),先把短按标志清零,然后触发长按。在这段程序里,把自锁标志置位,是为了防止按住按键不松手后一直触发。
回复

使用道具 举报

ID:975054 发表于 2022-12-1 15:06 | 显示全部楼层
这里 sysTim=keyTim  可能另有他用吧!
回复

使用道具 举报

ID:1092741 发表于 2023-9-6 07:56 | 显示全部楼层
刚试过可以运行,实测长短按键很难区分开,所以无实用性
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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