从单片机基础到程序框架(全集 2019pdf版).pdf - 第408页
} void Syste mInitial( void) { TMOD=0x01; TH0=0xfc; TL0=0x66; EA=1; ET0=1; TR0=1; } void Delay (unsigned l ong u32Delay Time) { for(;u32 DelayTime>0 ;u32DelayT ime--); } void Perip heralInit ial(void) { } void BeepO p…

#include "REG52.H"
#define KEY_VOICE_TIME 50 //按键触发后发出的声音长度
#define KEY_FILTER_TIME 25 //按键滤波的“稳定时间”25ms
void T0_time();
void SystemInitial(void) ;
void Delay(unsigned long u32DelayTime) ;
void PeripheralInitial(void) ;
void BeepOpen(void);
void BeepClose(void);
void VoiceScan(void);
void KeyScan(void); //按键识别的驱动函数,放在定时中断里
void KeyTask(void); //按键任务函数,放在主函数内
sbit P3_4=P3^4;
sbit KEY_INPUT1=P2^2; //K1 按键识别的输入口。
sbit KEY_INPUT2=P2^1; //K2 按键识别的输入口。
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
volatile unsigned char vGu8KeySec=0; //按键的触发序号,全局变量意味着是其它函数的接口。
void main()
{
SystemInitial();
Delay(10000);
PeripheralInitial();
while(1)
{
KeyTask(); //按键任务函数
}
}
void T0_time() interrupt 1
{
VoiceScan();
KeyScan(); //按键识别的驱动函数
TH0=0xfc;
TL0=0x66;

}
void SystemInitial(void)
{
TMOD=0x01;
TH0=0xfc;
TL0=0x66;
EA=1;
ET0=1;
TR0=1;
}
void Delay(unsigned long u32DelayTime)
{
for(;u32DelayTime>0;u32DelayTime--);
}
void PeripheralInitial(void)
{
}
void BeepOpen(void)
{
P3_4=0;
}
void BeepClose(void)
{
P3_4=1;
}
void VoiceScan(void)
{
static unsigned char Su8Lock=0;
if(1==vGu8BeepTimerFlag&&vGu16BeepTimerCnt>0)
{
if(0==Su8Lock)
{
Su8Lock=1;
BeepOpen();

}
else
{
vGu16BeepTimerCnt--;
if(0==vGu16BeepTimerCnt)
{
Su8Lock=0;
BeepClose();
}
}
}
}
/* 注释一:
* 独立按键扫描的详细过程,以按键 K1 为例,如下:
* 第一步:平时没有按键被触发时,按键的自锁标志,去抖动延时计数器一直被清零。
* 第二步:一旦有按键被按下,去抖动延时计数器开始在定时中断函数里累加,在还没累加到
* 阀值 KEY_FILTER_TIME 时,如果在这期间由于受外界干扰或者按键抖动,而使
* IO 口突然瞬间触发成高电平,这个时候马上把延时计数器 Su16KeyCnt1 清零了,这个过程
* 非常巧妙,非常有效地去除瞬间的杂波干扰。以后凡是用到开关感应器的时候,
* 都可以用类似这样的方法去干扰。
* 第三步:如果按键按下的时间达到阀值 KEY_FILTER_TIME 时,则触发按键,把编号 vGu8KeySec 赋值。
* 同时,马上把自锁标志 Su8KeyLock1 置 1,防止按住按键不松手后一直触发。
* 第四步:等按键松开后,自锁标志 Su8KeyLock1 及时清零(解锁),为下一次自锁做准备。
* 第五步:以上整个过程,就是识别按键 IO 口下降沿触发的过程。
*/
void KeyScan(void) //此函数放在定时中断里每 1ms 扫描一次
{
static unsigned char Su8KeyLock1; //1 号按键的自锁
static unsigned int Su16KeyCnt1; //1 号按键的计时器
static unsigned char Su8KeyLock2; //2 号按键的自锁
static unsigned int Su16KeyCnt2; //2 号按键的计时器
//1 号按键
if(0!=KEY_INPUT1)//IO 是高电平,说明按键没有被按下,这时要及时清零一些标志位
{
Su8KeyLock1=0; //按键解锁
Su16KeyCnt1=0; //按键去抖动延时计数器清零,此行非常巧妙,是全场的亮点。
}
else if(0==Su8KeyLock1)//有按键按下,且是第一次被按下。这行很多初学者有疑问,请看专题分析。
{