找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1894|回复: 7
打印 上一主题 下一主题
收起左侧

一个按键实现长按,单击,多击源程序

  [复制链接]
跳转到指定楼层
楼主
ID:1123636 发表于 2024-11-20 15:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*===============================================================
功能:一个按键实现按键的长按,短按,多击
长按:按下有效,有长按,短按一般来讲都是松开有效
多击(包含单击):松开有效

按键按下的触发事件:(触发事件可以按需求修改)
长按:点亮Led0
单击:点亮Led1
双击:点亮Led2
三击:点亮Led3
===============================================================*/

/*============================注意事项==================================
1.关于Seg的变量和ucLed可以不必理会,
前者是数码管显示Reg_Test_Count,后者是按键按下后的触发事件。这两个大家可以自己更改
=======================================================================*/

/* 头文件声明区 */
#include <STC15F2K60S2.H>//单片机寄存器专用头文件
#include <Init.h>//初始化底层驱动专用头文件
#include <Led.h>//Led底层驱动专用头文件
#include <Key.h>//按键底层驱动专用头文件
#include <Seg.h>//数码管底层驱动专用头文件

sbit KEY4 = P3^3;    //定义了一个按键


/* 变量声明区 */

unsigned char Key_Slow_Down;                                                                  //按键减速专用变量
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};                               //数码管显示数据存放数组
unsigned char Seg_Pos;                                                                             //数码管扫描专用变量
unsigned int  Seg_Slow_Down;                                                                   //数码管减速专用变量
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};                                                //Led显示数据存放数组

/*变量*/
unsigned int Reg_Test_Count;                                                                      //测试用的一个变量,表示短按了多少次。这个可以自己定义一个
unsigned int Reg_Tick;                                                                                //表示每次按下的时间间隔是多少。初始值可以自己改,看后面的代码就知道了
unsigned int Reg_Key_Filter_50ms;                                                                //按下时滤波,我这里滤波50ms。
unsigned int Reg_Key_10ms;                                                                        //10ms计数

/*标志位*/
unsigned char Bit_Short_Press;                                                                                                //短按标志位               
unsigned char Bit_10ms;                                                                                                        //10ms定时到达标志位
/* 键盘处理函数 */
void Key_Proc()
{
        static unsigned int Reg_Key_Press_Time = 0;          //请记得标为静态变量
        if(Bit_10ms)                                                                                                                  //10ms进来一次
        {
                Bit_10ms = 0;
    if(KEY4==0)                                                                                                                           //如果按下了按键
                {
                        Reg_Tick = 50;                                                                                                   //给多击的时间间隔赋初值
                        if(++Reg_Key_Press_Time <=0 ) --Reg_Key_Press_Time;                                 //计量按键时间,并避免数据溢出        
                        if(Bit_Short_Press == 0)                  //判断短按标志位
                        {
                                if(++Reg_Key_Filter_50ms >= 5)                                                            //如果滤波时间到达了50ms
                                {
                                        Reg_Key_Filter_50ms = 0;                                                                    //滤波时间清0
                                        Reg_Test_Count++;                                                                                       
                                        Bit_Short_Press = 1;                                                                             //短按标志位置1
                                }
                        }               
                        if(Reg_Key_Press_Time >= 100)                                                                              //长按时间已经到达1s        
                        {
                                ucLed[0] = 1;                                                                                                //这里写事件,我这里写的点灯
                        }
    }
                else//松开
                {
                        Reg_Key_Filter_50ms = 0;                                                                                        //滤波的50ms只有检测到高电平立马清零,此次按键无效
                        Bit_Short_Press = 0;                                                                                                //短按标志位清零
                        Reg_Key_Press_Time = 0;                                                                                        //长按计数清零
                        if(Reg_Tick)                                                                                                        //如果多击时间间隔不为零
                        {
                                Reg_Tick--;                                                                                                               
                        }
                        if(Reg_Tick == 0)                                                                                                //只要减到0,就说明此时我已经不再按下按键了,开始写多击事件
                        {
                                if(Reg_Test_Count == 1)                                                                                 //如果按下一次
                                {
                                        ucLed[1] = 1;                                                                                         //写按下一次的事件,这个可以自己改,我写的点灯
                                }
                                else if(Reg_Test_Count == 2)                                                                          //如果按下两次
                                {
                                        ucLed[2] = 1;                                                                                          //同上
                                }
                                else if(Reg_Test_Count == 3)                                                                           //如果按下三次
                                {
                                        ucLed[3] = 1;                                                                                            //同上
                                }
                                Reg_Test_Count = 0;                                                                                                 //Reg_Test_Count清零,等待执行下一次多击事件
                                        //到这里就完整的执行了一次多击事件,注意Reg_Test_Count一定要清零。
                        }              
    }
        }
}

/* 信息处理函数 */
void Seg_Proc()
{
        if(Seg_Slow_Down) return;
        Seg_Slow_Down = 1;//数码管减速程序
        Seg_Buf[0] = Reg_Test_Count%10;
}


/* 定时器0中断初始化函数 */
void Timer0Init(void)                //1毫秒@12.000MHz
{
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式
        TL0 = 0x18;                //设置定时初始值
        TH0 = 0xFC;                //设置定时初始值
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
        ET0 = 1;    //定时器中断0打开
        EA = 1;     //总中断打开
}


/* 定时器0中断服务函数 */
void Timer0Server() interrupt 1
{  
        if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//键盘减速专用
        if(++Seg_Slow_Down == 100) Seg_Slow_Down = 0;//数码管减速专用
        if(++Seg_Pos == 8) Seg_Pos = 0;//数码管显示专用
        if(++Reg_Key_10ms >= 10)
        {
                Reg_Key_10ms = 0;
                Bit_10ms = 1;
        }
        Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
        Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
}

/* Main */
void main()
{
        System_Init();
        Timer0Init();
        
        while (1)
        {
                Key_Proc();
                Seg_Proc();
               
        }
}

评分

参与人数 2黑币 +55 收起 理由
STC庄伟 + 5 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏12 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:143767 发表于 2024-11-21 11:07 | 只看该作者
真的很好,好好学习一下,感谢楼主奉献
回复

使用道具 举报

板凳
ID:143767 发表于 2024-11-21 11:18 | 只看该作者
请问楼主,四个led接在单片机的哪个端口上了,谢谢
回复

使用道具 举报

地板
ID:229502 发表于 2024-11-21 13:32 | 只看该作者
按键代码处理,值得参考
回复

使用道具 举报

5#
ID:143767 发表于 2024-11-21 16:25 | 只看该作者
请问楼主,四个led接在单片机的哪个端口上了,P00-P07还是其他的IO口,谢谢
回复

使用道具 举报

6#
ID:1123636 发表于 2024-11-21 17:50 | 只看该作者
dj3365191 发表于 2024-11-21 11:18
请问楼主,四个led接在单片机的哪个端口上了,谢谢

任意IO就行,这个Led只是触发事件
回复

使用道具 举报

7#
ID:1143011 发表于 2025-1-28 10:47 | 只看该作者

真的很好,好好学习一下,感谢楼主奉献
回复

使用道具 举报

8#
ID:595237 发表于 2025-2-2 20:19 | 只看该作者
dj3365191 发表于 2024-11-21 16:25
请问楼主,四个led接在单片机的哪个端口上了,P00-P07还是其他的IO口,谢谢

#include <Led.h>//Led底层驱动专用头文件-------四个led接在这个led.h的端口上了-
#include <Key.h>//按键底层驱动专用头文件
#include <Seg.h>//数码管底层驱动专用头文件

缺少Led,按键,数码管
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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