【独立按键组成的组合按键、短按与长按、按住不松手的均匀触发】

(1)单击K1点亮LED,单击K2熄灭LED,K1与K2组合按键蜂鸣器发声。

#include "reg52.h"
#define KEY_VOICE_TIME 50//按键触发后发出的声音长度
#define KEY_FILTER_TIME 25//按键滤波的“稳定时间”25ms
// #define KEY_INTERVAL_TIME 400//连续两次单击之间的最大有效时间
sbit beep=P2^3;//蜂鸣器
sbit P1_4=P1^4;//LED
sbit KEY_INPUT1=P3^4;//按键识别输入口
sbit KEY_INPUT2=P3^5;
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
// unsigned char Gu8LedStatus=0;//LED灯的状态,0代表灭,1代表亮
volatile unsigned char vGu8SingleKeySec=0;//单击按键的触发序号
volatile unsigned char vGu8CombinationKeySec=0;//组合按键的触发序号
void SystemInitial()
{
    TMOD=0x01;
    TH0=0xfc;
    TL0=0x66;
    EA=1;
    ET0=1;
    TR0=1;
}
void Delay(unsigned long u32DelayTime)
{
    for(;u32DelayTime>0;u32DelayTime--);
}
void LedOpen()
{
    P1_4=0;
}
void LedClose()
{
    P1_4=1;
}
void PeripheralInitial()
{//led初始化没有放在SystemInitial中是因为led显示内容对上电瞬间要求不高,如果是控制继电器则应该放在SystemInitial中
    LedClose();
}
void BeepOpen()
{
    beep=0;
}
void BeepClose()
{
    beep=1;
}
void VoiceScan()//蜂鸣器的非阻塞驱动."驱动层"的驱动函数,放在定时中断函数里每1ms扫描一次,保证声音长度的一致性
{
    static unsigned char Su8Lock=0;
    if(1==vGu8BeepTimerFlag && vGu16BeepTimerCnt>0)
    {
        if(0==Su8Lock)
        {
            Su8Lock=1;//触发声音后自锁起来,避免BeepOpen()被重复扫描影响执行效率,发声时只执行一次BeepOpen()函数即可
            BeepOpen();//蜂鸣器发声,封装成函数为了代码的移植性
        }
        else//借用else结构实现先发声下一次中断再开始计时
        {
            vGu16BeepTimerCnt--;
            if(0==vGu16BeepTimerCnt)
            {
                Su8Lock=0;//关闭声音后及时解锁为下一次触发做准备
                BeepClose();
            }
        }
    }
}
void KeyScan()//非阻塞,放在中断函数中"清零式滤波"
{
    static unsigned char Su8KeyLock1;//1号按键的自锁
    static unsigned int Su16KeyCnt1;//1号按键的计时器
    static unsigned char Su8KeyLock2;
    static unsigned int Su16KeyCnt2;
    static unsigned char Su8CombinationKeyLock;//组合按键自锁
    static unsigned int Su16CombinationKeyCnt;//组合按键计数器

    if(0!=KEY_INPUT1 || 0!=KEY_INPUT2)//关键语句,同时按下即都是0时退出语句
    {
        Su8CombinationKeyLock=0;//
        Su16CombinationKeyCnt=0;
    }
    else if(0 == Su8CombinationKeyLock)//else设计巧妙,等效于if(0==KEY_INPUT1 && 0==KEY_INPUT2 && 0==Su8CombinationKeyLock)
    {
        Su16CombinationKeyCnt++;
        if(Su16CombinationKeyCnt>=KEY_FILTER_TIME)//滤波的稳定时间
        {
            Su8CombinationKeyLock=1;//自锁避免一直触发
            vGu8CombinationKeySec=1;//组合按键按下标志位
        }
    }

    if(0!=KEY_INPUT1)//IO口是高电平,没有按键按下,”去抖动延时计数器“一直被清零,如果受到外界或抖动干扰就可以去除瞬间的杂波干扰
    {
        Su8KeyLock1=0;//按键解锁
        Su16KeyCnt1=0;//”去抖动延时计数器“,按键去抖动的重要语句,在抖动过程中一旦有高电平立刻置0直到稳定
    }
    else if(0 == Su8KeyLock1)//说明按键被按下,else设计很巧妙相当于KEY_INPUT1==0
    {
        Su16KeyCnt1++;//累加的过程就是在滤波,若在累加过程中受到干扰IO口触发高电平,这时马上将Su16KeyCnt1置0,即去除瞬间杂波
        if(Su16KeyCnt1>=KEY_FILTER_TIME)//滤波的“稳定时间”
        {
            Su8KeyLock1=1;//按键自锁标志位,一旦触发按键标志位置1,防止按键按键按住不松手时不断触发按键
            vGu8SingleKeySec=1;//按键1单击触发
        }
    }
    if(0!=KEY_INPUT2)
    {
        Su8KeyLock2=0;
        Su16KeyCnt2=0;
    }
    else if(0 == Su8KeyLock2)
    {
        Su16KeyCnt2++;
        if(Su16KeyCnt2>=KEY_FILTER_TIME)
        {
            Su8KeyLock2=1;
            vGu8SingleKeySec=2;
        }
    }
}
void SingleKeyTask()
{
    if(0==vGu8SingleKeySec)
    {
        return;//序号为0无按键触发,退出当前函数.因为当按键多达几十个时就能避免主函数每次进入KeyTask函数时进入switch多次判断,可能会更高效
    }
    switch(vGu8SingleKeySec)
    {
        case 1:
            LedOpen();
            vGu8SingleKeySec=0;//响应按键服务程序后按键编号清零避免一直触发
            break;
        case 2:
            LedClose();
            vGu8SingleKeySec=0;
            break;
    }
}
void CombinationKeyTask()
{
    if(0==vGu8CombinationKeySec)
    {
        return;
    }
    switch(vGu8CombinationKeySec)
    {
        case 1:
            vGu8BeepTimerFlag=0;
            vGu16BeepTimerCnt=KEY_VOICE_TIME;//"应用层"只需赋值,就发出固定时间长度的声音
            vGu8BeepTimerFlag=1;
            vGu8CombinationKeySec=0;//响应按键服务程序后,按键编号清零避免一直触发
            break;
    }
}
void main()
{
    SystemInitial();
    Delay(10000);
    PeripheralInitial();
    while(1)
    {
        SingleKeyTask();
        CombinationKeyTask();
    }
}
void T0_time() interrupt 1
{
    VoiceScan();
    KeyScan();//因为KeyScan是特殊函数放在中断函数里,涉及到IO口输入信号的滤波,滤波就涉及到时间的及时性和均匀性,放在中断中更能保证时间的一致性
    TH0=0xfc;//如蜂鸣器驱动,动态数码管驱动,按键扫描驱动
    TL0=0x66;
}

(2)“电脑键盘式”组合按键。如同电脑键盘的“crtl+c”,先按下ctrl再按c才能触发。
K1按下一次LED亮或灭;先按住K2再按住K1触发组合键蜂鸣器响。

#include "reg52.h"
#define KEY_VOICE_TIME 50//按键触发后发出的声音长度
#define KEY_FILTER_TIME 25//按键滤波的“稳定时间”25ms
// #define KEY_INTERVAL_TIME 400//连续两次单击之间的最大有效时间
sbit beep=P2^3;//蜂鸣器
sbit P1_4=P1^4;//LED
sbit KEY_INPUT1=P3^4;//按键识别输入口
sbit KEY_INPUT2=P3^5;
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
unsigned char Gu8LedStatus=0;//LED灯的状态,0代表灭,1代表亮
volatile unsigned char vGu8SingleKeySec=0;//单击按键的触发序号
volatile unsigned char vGu8CombinationKeySec=0;//组合按键的触发序号
void SystemInitial()
{
    TMOD=0x01;
    TH0=0xfc;
    TL0=0x66;
    EA=1;
    ET0=1;
    TR0=1;
}
void Delay(unsigned long u32DelayTime)
{
    for(;u32DelayTime>0;u32DelayTime--);
}
void LedOpen()
{
    P1_4=0;
}
void LedClose()
{
    P1_4=1;
}
void PeripheralInitial()
{//led初始化没有放在SystemInitial中是因为led显示内容对上电瞬间要求不高,如果是控制继电器则应该放在SystemInitial中
    LedClose();
}
void BeepOpen()
{
    beep=0;
}
void BeepClose()
{
    beep=1;
}
void VoiceScan()//蜂鸣器的非阻塞驱动."驱动层"的驱动函数,放在定时中断函数里每1ms扫描一次,保证声音长度的一致性
{
    static unsigned char Su8Lock=0;
    if(1==vGu8BeepTimerFlag && vGu16BeepTimerCnt>0)
    {
        if(0==Su8Lock)
        {
            Su8Lock=1;//触发声音后自锁起来,避免BeepOpen()被重复扫描影响执行效率,发声时只执行一次BeepOpen()函数即可
            BeepOpen();//蜂鸣器发声,封装成函数为了代码的移植性
        }
        else//借用else结构实现先发声下一次中断再开始计时
        {
            vGu16BeepTimerCnt--;
            if(0==vGu16BeepTimerCnt)
            {
                Su8Lock=0;//关闭声音后及时解锁为下一次触发做准备
                BeepClose();
            }
        }
    }
}
void KeyScan()
{
    static unsigned char Su8KeyLock1;
    static unsigned int Su16KeyCnt1;

    if(0!=KEY_INPUT1)
    {
        Su8KeyLock1=0;
        Su16KeyCnt1=0;
    }
    else if(0 == Su8KeyLock1)
    {
        Su16KeyCnt1++;
        if(Su16KeyCnt1>=KEY_FILTER_TIME)
        {
            if(0 == KEY_INPUT2)//"电脑组合按键关键语句",只有先按下K2再按下K1才能触发组合按键
            {
                Su8KeyLock1=1;
                vGu8CombinationKeySec=1;
            }
            else
            {
                Su8KeyLock1=1;
                vGu8SingleKeySec=1;
            }
        }
    }
}

   
void SingleKeyTask()
{
    if(0==vGu8SingleKeySec)
    {
        return;//序号为0无按键触发,退出当前函数.因为当按键多达几十个时就能避免主函数每次进入KeyTask函数时进入switch多次判断,可能会更高效
    }
    switch(vGu8SingleKeySec)
    {
        case 1:
            if(0 == Gu8LedStatus)
            {
                Gu8LedStatus=1;
                LedOpen();
            }
            else
            {
                Gu8LedStatus=0;
                LedClose();
            }
            vGu8SingleKeySec=0;
            break;
    }
}
void CombinationKeyTask()
{
    if(0==vGu8CombinationKeySec)
    {
        return;
    }
    switch(vGu8CombinationKeySec)
    {
        case 1:
            vGu8BeepTimerFlag=0;
            vGu16BeepTimerCnt=KEY_VOICE_TIME;//"应用层"只需赋值,就发出固定时间长度的声音
            vGu8BeepTimerFlag=1;
            vGu8CombinationKeySec=0;//响应按键服务程序后,按键编号清零避免一直触发
            break;
    }
}
void main()
{
    SystemInitial();
    Delay(10000);
    PeripheralInitial();
    while(1)
    {
        SingleKeyTask();
        CombinationKeyTask();
    }
}
void T0_time() interrupt 1
{
    VoiceScan();
    KeyScan();//因为KeyScan是特殊函数放在中断函数里,涉及到IO口输入信号的滤波,滤波就涉及到时间的及时性和均匀性,放在中断中更能保证时间的一致性
    TH0=0xfc;//如蜂鸣器驱动,动态数码管驱动,按键扫描驱动
    TL0=0x66;
}

(3)独立按键的短按与长按
独立按键“短按”一次亮灭切换,“长按”一次蜂鸣器响

#include "reg52.h"
#define KEY_VOICE_TIME 50
#define KEY_SHOTR_TIME 25//短按时间
#define KEY_LONG_TIME 500//长按时间
sbit beep=P2^3;//蜂鸣器
sbit P1_4=P1^4;//LED
sbit KEY_INPUT1=P3^4;//按键识别输入口
// sbit KEY_INPUT2=P3^5;
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
unsigned char Gu8LedStatus=0;//LED灯的状态,0代表灭,1代表亮
volatile unsigned char vGu8SingleKeySec=0;
void SystemInitial()
{
    TMOD=0x01;
    TH0=0xfc;
    TL0=0x66;
    EA=1;
    ET0=1;
    TR0=1;
}
void Delay(unsigned long u32DelayTime)
{
    for(;u32DelayTime>0;u32DelayTime--);
}
void LedOpen()
{
    P1_4=0;
}
void LedClose()
{
    P1_4=1;
}
void PeripheralInitial()
{//led初始化没有放在SystemInitial中是因为led显示内容对上电瞬间要求不高,如果是控制继电器则应该放在SystemInitial中
    LedClose();
}
void BeepOpen()
{
    beep=0;
}
void BeepClose()
{
    beep=1;
}
void VoiceScan()
{
    static unsigned char Su8Lock=0;
    if(1==vGu8BeepTimerFlag && vGu16BeepTimerCnt>0)
    {
        if(0==Su8Lock)
        {
            Su8Lock=1;
            BeepOpen();
        }
        else
        {
            vGu16BeepTimerCnt--;
            if(0==vGu16BeepTimerCnt)
            {
                Su8Lock=0;
                BeepClose();
            }
        }
    }
}
void KeyScan()
{
    static unsigned char Su8KeyLock1;
    static unsigned int Su16KeyCnt1;
    static unsigned char Su8KeyShortFlag=0;

    if(0!=KEY_INPUT1)
    {
        Su8KeyLock1=0;
        Su16KeyCnt1=0;
        if(1 == Su8KeyShortFlag)
        {
            Su8KeyShortFlag=0;
            vGu8SingleKeySec=1;//松手后在短按时间内才触发短按
        }
    }
    else if(0 == Su8KeyLock1)
    {
        Su16KeyCnt1++;
        if(Su16KeyCnt1>=KEY_SHOTR_TIME)//到达短按时间
        {
            Su8KeyShortFlag=1;//短按标志很重要,松手才能触发短按
        }
        if(Su16KeyCnt1>=KEY_LONG_TIME)//到达长按时间
        {
            Su8KeyLock1=1;//触发自锁,避免一直触发长按
            Su8KeyShortFlag=0;//清除短按标志
            vGu8SingleKeySec=2;//触发长按
        }
    }
}

   
void SingleKeyTask()
{
    if(0==vGu8SingleKeySec)
    {
        return;
    }
    switch(vGu8SingleKeySec)
    {
        case 1:
            if(0 == Gu8LedStatus)
            {
                Gu8LedStatus=1;
                LedOpen();
            }
            else
            {
                Gu8LedStatus=0;
                LedClose();
            }
            vGu8SingleKeySec=0;
            break;
        case 2:
            vGu8BeepTimerFlag=0;
            vGu16BeepTimerCnt=KEY_VOICE_TIME;
            vGu8BeepTimerFlag=1;
            vGu8SingleKeySec=0;
            break;
    }
}
void main()
{
    SystemInitial();
    Delay(10000);
    PeripheralInitial();
    while(1)
    {
        SingleKeyTask();
    }
}
void T0_time() interrupt 1
{
    VoiceScan();
    KeyScan();
    TH0=0xfc;
    TL0=0x66;
}

(4)按键按住不松手的连续均匀触发
按下K1,跑马灯左边跑一步;按下K2,右边跑一步;按住K1或K2不松手连续触发,跑马灯连续跑;按键单击一次时蜂鸣器叫一次,连续触发时不鸣叫。

#include "reg52.h"
#define KEY_VOICE_TIME 50
#define KEY_SHORT_TIME 25//按键滤波的“稳定时间”25ms
#define KEY_ENTER_CONTINUITY_TIME 300//从单击到连击间隔时间
#define KEY_CONTINUITY_TIME 80//连击间隔时间
#define BUS_P1 P1//p1口连接8个led灯
sbit beep=P2^3;//蜂鸣器
sbit KEY_INPUT1=P3^4;//按键识别输入口
sbit KEY_INPUT2=P3^5;
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
unsigned char Gu8LedStatus=0;//1左移的位数
unsigned char Gu8DisplayUpdata=1;//显示的刷新标志
volatile unsigned char vGu8KeySec=0;//按键的触发序号
volatile unsigned char vGu8ShiedVoiceFlag=0;//屏蔽声音标志
void SystemInitial()
{
    TMOD=0x01;
    TH0=0xfc;
    TL0=0x66;
    EA=1;
    ET0=1;
    TR0=1;
}
void Delay(unsigned long u32DelayTime)
{
    for(;u32DelayTime>0;u32DelayTime--);
}
void PeripheralInitial()
{

}
void BeepOpen()
{
    beep=0;
}
void BeepClose()
{
    beep=1;
}
void VoiceScan()
{
    static unsigned char Su8Lock=0;
    if(1==vGu8BeepTimerFlag && vGu16BeepTimerCnt>0)
    {
        if(0==Su8Lock)
        {
            Su8Lock=1;
            BeepOpen();
        }
        else
        {
            vGu16BeepTimerCnt--;
            if(0==vGu16BeepTimerCnt)
            {
                Su8Lock=0;
                BeepClose();
            }
        }
    }
}
/*Gu8DisplayUpdata“显示刷新变量”在显示框架中很常见,目的是既能及时刷新显示,又能避免主函数
“不断执行显示代码”而影响程序效率*/
void DisplayTask()
{
    if(1 == Gu8DisplayUpdata)
    {
        Gu8DisplayUpdata=0;
        BUS_P1=~(1<<Gu8LedStatus);//1左移Gu8LedStatus位
    }
}
void KeyScan()
{
    static unsigned char Su8KeyLock1;
    static unsigned int Su16KeyCnt1;
    static unsigned int Su16KeyContinuityCnt1;

    static unsigned char Su8KeyLock2;
    static unsigned int Su16KeyCnt2;
    static unsigned int Su16KeyContinuityCnt2;

    if(0!=KEY_INPUT1)
    {
        Su8KeyLock1=0;
        Su16KeyCnt1=0;
        Su16KeyContinuityCnt1=0;
    }
    else if(0 == Su8KeyLock1)
    {
        Su16KeyCnt1++;
        if(Su16KeyCnt1>=KEY_SHORT_TIME)//按键滤波时间25ms
        {
            Su8KeyLock1=1;//自锁起来,按住不放进入连续触发检测
            vGu8KeySec=1;//触发一次K1按键
            Su16KeyCnt1=0;
        }
    }
    else if(Su16KeyCnt1<=KEY_ENTER_CONTINUITY_TIME)
    {
        Su16KeyCnt1++;//第一次按下按键之后到连续触发的时间间隔300ms
    }
    else//按住300ms后任然不放手进入连续触发
    {
        Su16KeyContinuityCnt1++;
        if(Su16KeyContinuityCnt1>=KEY_CONTINUITY_TIME)//每80ms触发一次
        {
            Su16KeyContinuityCnt1=0;
            vGu8KeySec=1;//触发
            vGu8ShiedVoiceFlag=1;//连续触发屏蔽按键触发的声音
        }
    }

    if(0!=KEY_INPUT2)
    {
        Su8KeyLock2=0;
        Su16KeyCnt2=0;
        Su16KeyContinuityCnt2=0;
    }
    else if(0 == Su8KeyLock2)
    {
        Su16KeyCnt2++;
        if(Su16KeyCnt2>=KEY_SHORT_TIME)
        {
            Su8KeyLock2=1;
            vGu8KeySec=2;//触发一次K2按键
            Su16KeyCnt2=0;
        }
    }
    else if(Su16KeyCnt2<=KEY_ENTER_CONTINUITY_TIME)
    {
        Su16KeyCnt2++;
    }
    else//按住300ms后任然不放手进入连续触发
    {
        Su16KeyContinuityCnt2++;
        if(Su16KeyContinuityCnt2>=KEY_CONTINUITY_TIME)//每80ms触发一次
        {
            Su16KeyContinuityCnt2=0;
            vGu8KeySec=2;//触发
            vGu8ShiedVoiceFlag=1;//屏蔽按键触发的声音
        }
    }
}

   
void KeyTask()
{
    if(0==vGu8KeySec)
    {
        return;
    }
    switch(vGu8KeySec)
    {
        case 1:
            if(Gu8LedStatus>0)
            {
                Gu8LedStatus--;//跑马灯左跑
                Gu8DisplayUpdata=1;//刷新显示
            }
            if(0==vGu8ShiedVoiceFlag)//没有屏蔽声音
            {
                vGu8BeepTimerFlag=0;
                vGu16BeepTimerCnt=KEY_VOICE_TIME;
                vGu8BeepTimerFlag=1;
            }
            vGu8ShiedVoiceFlag=0;
            vGu8KeySec=0;
            break;
        case 2:
            if(Gu8LedStatus<7)
            {
                Gu8LedStatus++;
                Gu8DisplayUpdata=1;
            }
            if(0==vGu8ShiedVoiceFlag)
            {
                vGu8BeepTimerFlag=0;
                vGu16BeepTimerCnt=KEY_VOICE_TIME;
                vGu8BeepTimerFlag=1;
            }
            vGu8ShiedVoiceFlag=0;
            vGu8KeySec=0;
            break;
    }
}

void main()
{
    SystemInitial();
    Delay(10000);
    PeripheralInitial();
    while(1)
    {
        KeyTask();
        DisplayTask();//显示led任务函数
    }
}
void T0_time() interrupt 1
{
    VoiceScan();
    KeyScan();
    TH0=0xfc;
    TL0=0x66;
}

(5)独立按键按住不松手的“先加速后匀速”的触发
功能:触发K1,自减1,最小值为0;触发K2,自加1,最大值800;单击一次蜂鸣器鸣叫一次,由单击进入连击蜂鸣器不鸣叫。

#include "reg52.h"
#define KEY_VOICE_TIME 50
#define KEY_SHORT_TIME 25//按键滤波的“稳定时间”25ms
#define KEY_ENTER_CONTINUITY_TIME 300//从单击到连击间隔时间
#define KEY_CONTINUITY_INITIAL_TIME 80//连击间隔时间
#define BUS_P1 P1//p1口连接8个led灯
#define KEY_SUB_DA_TIME 20//按键加速时每次减小的时间
#define KEY_CONTINUITY_MIN_TIME 5//加速之后匀速的间隔时间
sbit beep=P2^3;//蜂鸣器
sbit KEY_INPUT1=P3^4;//按键识别输入口
sbit KEY_INPUT2=P3^5;
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
unsigned int Gu16SetData=0;//"加速匀速的设置参数",0-800
unsigned char Gu8DisplayUpdata=1;//显示的刷新标志
volatile unsigned char vGu8KeySec=0;//按键的触发序号
volatile unsigned char vGu8ShiedVoiceFlag=0;//屏蔽声音标志
void SystemInitial()
{
    TMOD=0x01;
    TH0=0xfc;
    TL0=0x66;
    EA=1;
    ET0=1;
    TR0=1;
}
void Delay(unsigned long u32DelayTime)
{
    for(;u32DelayTime>0;u32DelayTime--);
}
void PeripheralInitial()
{

}
void BeepOpen()
{
    beep=0;
}
void BeepClose()
{
    beep=1;
}
void VoiceScan()
{
    static unsigned char Su8Lock=0;
    if(1==vGu8BeepTimerFlag && vGu16BeepTimerCnt>0)
    {
        if(0==Su8Lock)
        {
            Su8Lock=1;
            BeepOpen();
        }
        else
        {
            vGu16BeepTimerCnt--;
            if(0==vGu16BeepTimerCnt)
            {
                Su8Lock=0;
                BeepClose();
            }
        }
    }
}
/*Gu8DisplayUpdata“显示刷新变量”在显示框架中很常见,目的是既能及时刷新显示,又能避免主函数
“不断执行显示代码”而影响程序效率*/
void DisplayTask()
{
    if(1 == Gu8DisplayUpdata)//需要刷新一次
    {
        Gu8DisplayUpdata=0;
        if(Gu16SetData<100)
        {
            BUS_P1=~(1<<0);
        }
        else if(Gu16SetData<200)
        {
            BUS_P1=~(1<<1);
        }
        else if(Gu16SetData<300)
        {
            BUS_P1=~(1<<2);
        }
        else if(Gu16SetData<400)
        {
            BUS_P1=~(1<<3);
        }
        else if(Gu16SetData<500)
        {
            BUS_P1=~(1<<4);
        }
        else if(Gu16SetData<600)
        {
            BUS_P1=~(1<<5);
        }
        else if(Gu16SetData<700)
        {
            BUS_P1=~(1<<6);
        }
        else
        {
            BUS_P1=~(1<<7);
        }
    }
}
void KeyScan()
{
    static unsigned char Su8KeyLock1;
    static unsigned int Su16KeyCnt1;
    static unsigned int Su16KeyContinuityCnt1;
    static unsigned int Su16KeyContinuityTime1=KEY_CONTINUITY_INITIAL_TIME;

    static unsigned char Su8KeyLock2;
    static unsigned int Su16KeyCnt2;
    static unsigned int Su16KeyContinuityCnt2;
    static unsigned int Su16KeyContinuityTime2=KEY_CONTINUITY_INITIAL_TIME;

    if(0!=KEY_INPUT1)
    {
        Su8KeyLock1=0;
        Su16KeyCnt1=0;
        Su16KeyContinuityCnt1=0;
        Su16KeyContinuityTime1=KEY_CONTINUITY_INITIAL_TIME;
    }
    else if(0 == Su8KeyLock1)
    {
        Su16KeyCnt1++;
        if(Su16KeyCnt1>=KEY_SHORT_TIME)//按键滤波时间25ms
        {
            Su8KeyLock1=1;//自锁起来,按住不放进入连续触发检测
            vGu8KeySec=1;//触发一次K1按键
            Su16KeyCnt1=0;
        }
    }
    else if(Su16KeyCnt1<=KEY_ENTER_CONTINUITY_TIME)
    {
        Su16KeyCnt1++;//第一次按下按键之后到连续触发的时间间隔300ms
    }
    else//按住300ms后任然不放手进入连续触发
    {
        Su16KeyContinuityCnt1++;
        if(Su16KeyContinuityCnt1>=Su16KeyContinuityTime1)//自加或自减Su16KeyContinuityTime1进行加速
        {
            Su16KeyContinuityCnt1=0;
            vGu8KeySec=1;//触发
            vGu8ShiedVoiceFlag=1;//连续触发屏蔽按键触发的声音
            if(Su16KeyContinuityTime1>=KEY_SUB_DA_TIME)
            {
                Su16KeyContinuityTime1=Su16KeyContinuityTime1-KEY_SUB_DA_TIME;//数值不断减小触发速度加快
            }
            if(Su16KeyContinuityTime1<KEY_CONTINUITY_MIN_TIME)//到达最小时间间隔时匀速
            {
                Su16KeyContinuityTime1=KEY_CONTINUITY_MIN_TIME;//匀速的时间间隔
            }
        }
    }

    if(0!=KEY_INPUT2)
    {
        Su8KeyLock2=0;
        Su16KeyCnt2=0;
        Su16KeyContinuityCnt2=0;
        Su16KeyContinuityTime2=KEY_CONTINUITY_INITIAL_TIME;
    }
    else if(0 == Su8KeyLock2)
    {
        Su16KeyCnt2++;
        if(Su16KeyCnt2>=KEY_SHORT_TIME)
        {
            Su8KeyLock2=1;//自锁起来,按住不放进入连续触发检测
            vGu8KeySec=2;//触发一次K1按键
            Su16KeyCnt2=0;
        }
    }
    else if(Su16KeyCnt2<=KEY_ENTER_CONTINUITY_TIME)
    {
        Su16KeyCnt2++;//第一次按下按键之后到连续触发的时间间隔300ms
    }
    else//按住300ms后任然不放手进入连续触发
    {
        Su16KeyContinuityCnt2++;
        if(Su16KeyContinuityCnt2>=Su16KeyContinuityTime2)//自加或自减Su16KeyContinuityTime1进行加速
        {
            Su16KeyContinuityCnt2=0;
            vGu8KeySec=2;//触发
            vGu8ShiedVoiceFlag=1;//连续触发屏蔽按键触发的声音
            if(Su16KeyContinuityTime2>=KEY_SUB_DA_TIME)
            {
                Su16KeyContinuityTime2=Su16KeyContinuityTime2-KEY_SUB_DA_TIME;//数值不断减小触发速度加快
            }
            if(Su16KeyContinuityTime2<KEY_CONTINUITY_MIN_TIME)//到达最小时间间隔时匀速
            {
                Su16KeyContinuityTime2=KEY_CONTINUITY_MIN_TIME;//匀速的时间间隔
            }
        }
    }
}

   
void KeyTask()
{
    if(0==vGu8KeySec)
    {
        return;
    }
    switch(vGu8KeySec)
    {
        case 1://K1按键
            if(Gu16SetData>0)
            {
                Gu16SetData--;//跑马灯左跑
                Gu8DisplayUpdata=1;//刷新显示
            }
            if(0==vGu8ShiedVoiceFlag)//没有屏蔽声音
            {
                vGu8BeepTimerFlag=0;
                vGu16BeepTimerCnt=KEY_VOICE_TIME;
                vGu8BeepTimerFlag=1;
            }
            vGu8ShiedVoiceFlag=0;
            vGu8KeySec=0;
            break;
        case 2://K2按键
            if(Gu16SetData<800)
            {
                Gu16SetData++;
                Gu8DisplayUpdata=1;
            }
            if(0==vGu8ShiedVoiceFlag)
            {
                vGu8BeepTimerFlag=0;
                vGu16BeepTimerCnt=KEY_VOICE_TIME;
                vGu8BeepTimerFlag=1;
            }
            vGu8ShiedVoiceFlag=0;
            vGu8KeySec=0;
            break;
    }
}

void main()
{
    SystemInitial();
    Delay(10000);
    PeripheralInitial();
    while(1)
    {
        KeyTask();
        DisplayTask();//显示led任务函数
    }
}
void T0_time() interrupt 1
{
    VoiceScan();
    KeyScan();
    TH0=0xfc;
    TL0=0x66;
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值