标题: 一个按键实现长按,单击,多击源程序 [打印本页]

作者: 赵八百    时间: 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();
               
        }
}


作者: dj3365191    时间: 2024-11-21 11:07
真的很好,好好学习一下,感谢楼主奉献
作者: dj3365191    时间: 2024-11-21 11:18
请问楼主,四个led接在单片机的哪个端口上了,谢谢
作者: huangjingjie    时间: 2024-11-21 13:32
按键代码处理,值得参考
作者: dj3365191    时间: 2024-11-21 16:25
请问楼主,四个led接在单片机的哪个端口上了,P00-P07还是其他的IO口,谢谢
作者: 赵八百    时间: 2024-11-21 17:50
dj3365191 发表于 2024-11-21 11:18
请问楼主,四个led接在单片机的哪个端口上了,谢谢

任意IO就行,这个Led只是触发事件
作者: w645053932    时间: 2025-1-28 10:47

真的很好,好好学习一下,感谢楼主奉献
作者: juncedz    时间: 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,按键,数码管




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1