找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1951|回復(fù): 7
打印 上一主題 下一主題
收起左側(cè)

一個(gè)按鍵實(shí)現(xiàn)長按,單擊,多擊源程序

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1123636 發(fā)表于 2024-11-20 15:59 | 只看該作者 回帖獎勵(lì) |倒序?yàn)g覽 |閱讀模式
/*===============================================================
功能:一個(gè)按鍵實(shí)現(xiàn)按鍵的長按,短按,多擊
長按:按下有效,有長按,短按一般來講都是松開有效
多擊(包含單擊):松開有效

按鍵按下的觸發(fā)事件:(觸發(fā)事件可以按需求修改)
長按:點(diǎn)亮Led0
單擊:點(diǎn)亮Led1
雙擊:點(diǎn)亮Led2
三擊:點(diǎn)亮Led3
===============================================================*/

/*============================注意事項(xiàng)==================================
1.關(guān)于Seg的變量和ucLed可以不必理會,
前者是數(shù)碼管顯示Reg_Test_Count,后者是按鍵按下后的觸發(fā)事件。這兩個(gè)大家可以自己更改
=======================================================================*/

/* 頭文件聲明區(qū) */
#include <STC15F2K60S2.H>//單片機(jī)寄存器專用頭文件
#include <Init.h>//初始化底層驅(qū)動專用頭文件
#include <Led.h>//Led底層驅(qū)動專用頭文件
#include <Key.h>//按鍵底層驅(qū)動專用頭文件
#include <Seg.h>//數(shù)碼管底層驅(qū)動專用頭文件

sbit KEY4 = P3^3;    //定義了一個(gè)按鍵


/* 變量聲明區(qū) */

unsigned char Key_Slow_Down;                                                                  //按鍵減速專用變量
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};                               //數(shù)碼管顯示數(shù)據(jù)存放數(shù)組
unsigned char Seg_Pos;                                                                             //數(shù)碼管掃描專用變量
unsigned int  Seg_Slow_Down;                                                                   //數(shù)碼管減速專用變量
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};                                                //Led顯示數(shù)據(jù)存放數(shù)組

/*變量*/
unsigned int Reg_Test_Count;                                                                      //測試用的一個(gè)變量,表示短按了多少次。這個(gè)可以自己定義一個(gè)
unsigned int Reg_Tick;                                                                                //表示每次按下的時(shí)間間隔是多少。初始值可以自己改,看后面的代碼就知道了
unsigned int Reg_Key_Filter_50ms;                                                                //按下時(shí)濾波,我這里濾波50ms。
unsigned int Reg_Key_10ms;                                                                        //10ms計(jì)數(shù)

/*標(biāo)志位*/
unsigned char Bit_Short_Press;                                                                                                //短按標(biāo)志位               
unsigned char Bit_10ms;                                                                                                        //10ms定時(shí)到達(dá)標(biāo)志位
/* 鍵盤處理函數(shù) */
void Key_Proc()
{
        static unsigned int Reg_Key_Press_Time = 0;          //請記得標(biāo)為靜態(tài)變量
        if(Bit_10ms)                                                                                                                  //10ms進(jìn)來一次
        {
                Bit_10ms = 0;
    if(KEY4==0)                                                                                                                           //如果按下了按鍵
                {
                        Reg_Tick = 50;                                                                                                   //給多擊的時(shí)間間隔賦初值
                        if(++Reg_Key_Press_Time <=0 ) --Reg_Key_Press_Time;                                 //計(jì)量按鍵時(shí)間,并避免數(shù)據(jù)溢出        
                        if(Bit_Short_Press == 0)                  //判斷短按標(biāo)志位
                        {
                                if(++Reg_Key_Filter_50ms >= 5)                                                            //如果濾波時(shí)間到達(dá)了50ms
                                {
                                        Reg_Key_Filter_50ms = 0;                                                                    //濾波時(shí)間清0
                                        Reg_Test_Count++;                                                                                       
                                        Bit_Short_Press = 1;                                                                             //短按標(biāo)志位置1
                                }
                        }               
                        if(Reg_Key_Press_Time >= 100)                                                                              //長按時(shí)間已經(jīng)到達(dá)1s        
                        {
                                ucLed[0] = 1;                                                                                                //這里寫事件,我這里寫的點(diǎn)燈
                        }
    }
                else//松開
                {
                        Reg_Key_Filter_50ms = 0;                                                                                        //濾波的50ms只有檢測到高電平立馬清零,此次按鍵無效
                        Bit_Short_Press = 0;                                                                                                //短按標(biāo)志位清零
                        Reg_Key_Press_Time = 0;                                                                                        //長按計(jì)數(shù)清零
                        if(Reg_Tick)                                                                                                        //如果多擊時(shí)間間隔不為零
                        {
                                Reg_Tick--;                                                                                                               
                        }
                        if(Reg_Tick == 0)                                                                                                //只要減到0,就說明此時(shí)我已經(jīng)不再按下按鍵了,開始寫多擊事件
                        {
                                if(Reg_Test_Count == 1)                                                                                 //如果按下一次
                                {
                                        ucLed[1] = 1;                                                                                         //寫按下一次的事件,這個(gè)可以自己改,我寫的點(diǎn)燈
                                }
                                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清零,等待執(zhí)行下一次多擊事件
                                        //到這里就完整的執(zhí)行了一次多擊事件,注意Reg_Test_Count一定要清零。
                        }              
    }
        }
}

/* 信息處理函數(shù) */
void Seg_Proc()
{
        if(Seg_Slow_Down) return;
        Seg_Slow_Down = 1;//數(shù)碼管減速程序
        Seg_Buf[0] = Reg_Test_Count%10;
}


/* 定時(shí)器0中斷初始化函數(shù) */
void Timer0Init(void)                //1毫秒@12.000MHz
{
        AUXR &= 0x7F;                //定時(shí)器時(shí)鐘12T模式
        TMOD &= 0xF0;                //設(shè)置定時(shí)器模式
        TL0 = 0x18;                //設(shè)置定時(shí)初始值
        TH0 = 0xFC;                //設(shè)置定時(shí)初始值
        TF0 = 0;                //清除TF0標(biāo)志
        TR0 = 1;                //定時(shí)器0開始計(jì)時(shí)
        ET0 = 1;    //定時(shí)器中斷0打開
        EA = 1;     //總中斷打開
}


/* 定時(shí)器0中斷服務(wù)函數(shù) */
void Timer0Server() interrupt 1
{  
        if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//鍵盤減速專用
        if(++Seg_Slow_Down == 100) Seg_Slow_Down = 0;//數(shù)碼管減速專用
        if(++Seg_Pos == 8) Seg_Pos = 0;//數(shù)碼管顯示專用
        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();
               
        }
}

評分

參與人數(shù) 2黑幣 +55 收起 理由
STC莊偉 + 5 很給力!
admin + 50 共享資料的黑幣獎勵(lì)!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏12 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:143767 發(fā)表于 2024-11-21 11:07 | 只看該作者
真的很好,好好學(xué)習(xí)一下,感謝樓主奉獻(xiàn)
回復(fù)

使用道具 舉報(bào)

板凳
ID:143767 發(fā)表于 2024-11-21 11:18 | 只看該作者
請問樓主,四個(gè)led接在單片機(jī)的哪個(gè)端口上了,謝謝
回復(fù)

使用道具 舉報(bào)

地板
ID:229502 發(fā)表于 2024-11-21 13:32 | 只看該作者
按鍵代碼處理,值得參考
回復(fù)

使用道具 舉報(bào)

5#
ID:143767 發(fā)表于 2024-11-21 16:25 | 只看該作者
請問樓主,四個(gè)led接在單片機(jī)的哪個(gè)端口上了,P00-P07還是其他的IO口,謝謝
回復(fù)

使用道具 舉報(bào)

6#
ID:1123636 發(fā)表于 2024-11-21 17:50 | 只看該作者
dj3365191 發(fā)表于 2024-11-21 11:18
請問樓主,四個(gè)led接在單片機(jī)的哪個(gè)端口上了,謝謝

任意IO就行,這個(gè)Led只是觸發(fā)事件
回復(fù)

使用道具 舉報(bào)

7#
ID:1143011 發(fā)表于 2025-1-28 10:47 | 只看該作者

真的很好,好好學(xué)習(xí)一下,感謝樓主奉獻(xiàn)
回復(fù)

使用道具 舉報(bào)

8#
ID:595237 發(fā)表于 2025-2-2 20:19 | 只看該作者
dj3365191 發(fā)表于 2024-11-21 16:25
請問樓主,四個(gè)led接在單片機(jī)的哪個(gè)端口上了,P00-P07還是其他的IO口,謝謝

#include <Led.h>//Led底層驅(qū)動專用頭文件-------四個(gè)led接在這個(gè)led.h的端口上了-
#include <Key.h>//按鍵底層驅(qū)動專用頭文件
#include <Seg.h>//數(shù)碼管底層驅(qū)動專用頭文件

缺少Led,按鍵,數(shù)碼管
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表