从单片机基础到程序框架(全集 2019pdf版).pdf - 第453页
static unsig ned char Su8KeyL ock2; static unsig ned int Su1 6KeyCnt2; static unsig ned int Su1 6KeyContin uityCnt2; //连击 计数器 static unsig ned int Su1 6KeyContin uityTime2=K EY_CONTINU ITY_INITIAL _TIME; //动态时间 阀值 //K1 按…

BUS_P0=~(1<<1); //第 1 个灯亮
}
else if(Gu16SetData<300)
{
BUS_P0=~(1<<2); //第 2 个灯亮
}
else if(Gu16SetData<400)
{
BUS_P0=~(1<<3); //第 3 个灯亮
}
else if(Gu16SetData<500)
{
BUS_P0=~(1<<4); //第 4 个灯亮
}
else if(Gu16SetData<600)
{
BUS_P0=~(1<<5); //第 5 个灯亮
}
else if(Gu16SetData<700)
{
BUS_P0=~(1<<6); //第 6 个灯亮
}
else
{
BUS_P0=~(1<<7); //第 7 个灯亮
}
}
}
/* 注释二:
* 按键“先加速后匀速”的识别过程:
* 第一步:每次按一次就触发一次“单击”,如果按下去到松手的时间不超过 1 秒,则不会进入
* “连击”模式。
* 第二步:如果按下去不松手的时间超过 1 秒,则进入“连击”模式。按键触发的节奏
* 不断加快,直至到达某个极限值,然后以此极限值间隔匀速触发。这就是“先加速后匀速”。
*/
void KeyScan(void) //此函数放在定时中断里每 1ms 扫描一次
{
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; //动态时间阀值
//K1 按键
if(0!=KEY_INPUT1)//单个 K1 按键没有按下,及时清零一些标志。
{
Su8KeyLock1=0; //按键解锁
Su16KeyCnt1=0; //去抖动延时计数器清零,此行非常巧妙,是全场的亮点。
Su16KeyContinuityCnt1=0; //连击计数器
Su16KeyContinuityTime1=KEY_CONTINUITY_INITIAL_TIME; //动态时间阀值。重装初始值。
}
else if(0==Su8KeyLock1)//单个按键 K1 被按下
{
Su16KeyCnt1++; //累加定时中断次数,每一次累加额度是 1ms
if(Su16KeyCnt1>=KEY_SHORT_TIME) //按键的“滤波”时间 25ms
{
Su8KeyLock1=1; //“自锁”
vGu8KeySec=1; //触发一次 K1 按键
Su16KeyCnt1=0; //清零,为了下一步用来累加“从单击进入连击的间隔时间 300ms”
}
}
else if(Su16KeyCnt1<=KEY_ENTER_CONTINUITY_TIME)//按住不松手累加到 300ms
{
Su16KeyCnt1++; //累加定时中断次数,每一次累加额度是 1ms
}
else //按住累加到 300ms 后仍然不放手,这个时候进入有节奏的连续触发
{
Su16KeyContinuityCnt1++; //连击计数器开始累加,每一次累加额度是 1ms
if(Su16KeyContinuityCnt1>=Su16KeyContinuityTime1) //按住没松手,每隔一会就触发一次
{
Su16KeyContinuityCnt1=0; //清零,为了继续连击。
vGu8KeySec=1; //触发一次 K1 按键
vGu8ShieldVoiceFlag=1; //把当前按键触发的声音屏蔽掉
if(Su16KeyContinuityTime1>=KEY_SUB_DT_TIME)
{
//此数值不断被减小,按键的触发速度就不断变快
Su16KeyContinuityTime1=Su16KeyContinuityTime1-KEY_SUB_DT_TIME;//变快节奏
}
if(Su16KeyContinuityTime1<KEY_CONTINUITY_MIN_TIME) //最小间隔时间就是“高速匀速”
{
Su16KeyContinuityTime1=KEY_CONTINUITY_MIN_TIME; //最后以此最高速进行“匀速”

}
}
}
//K2 按键
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; //触发一次 K2 按键
Su16KeyCnt2=0;
}
}
else if(Su16KeyCnt2<=KEY_ENTER_CONTINUITY_TIME)
{
Su16KeyCnt2++;
}
else
{
Su16KeyContinuityCnt2++;
if(Su16KeyContinuityCnt2>=Su16KeyContinuityTime2)
{
Su16KeyContinuityCnt2=0;
vGu8KeySec=2; //触发一次 K2 按键
vGu8ShieldVoiceFlag=1;
if(Su16KeyContinuityTime2>=KEY_SUB_DT_TIME)
{
Su16KeyContinuityTime2=Su16KeyContinuityTime2-KEY_SUB_DT_TIME;
}
if(Su16KeyContinuityTime2<KEY_CONTINUITY_MIN_TIME)
{
Su16KeyContinuityTime2=KEY_CONTINUITY_MIN_TIME;