单片机学习笔记————51单片机累计主循环次数实现独立按键

一、使用proteus绘制简单的电路图,用于后续仿真

单片机学习笔记————51单片机累计主循环次数实现独立按键_第1张图片

二、编写程序

/********************************************************************************************************************
----	@Project:	Independent-KEY
----	@File:	main.c
----	@Edit:	ZHQ
----	@Version:	V1.0
----	@CreationTime:	20200505
----	@ModifiedTime:	20200505
----	@Description:	有两个独立按键,每按一个独立按键,蜂鸣器发出“滴”的一声后就停。
----	单片机:AT89C52
********************************************************************************************************************/
#include "reg52.h"

/*——————宏定义——————*/
#define FOSC 11059200L
#define T1MS (65536-FOSC/12/1000)   /*1ms timer calculation method in 12Tmode*/

#define const_voice_short  80   /*蜂鸣器短叫的持续时间*/

#define const_key_time1   1000  /*按键去抖动延时的时间*/
#define const_key_time2   1000  /*按键去抖动延时的时间*/

/*——————变量函数定义及声明——————*/
/*定义按键S1*/
sbit Key_S1 = P0^0;
/*定义按键S2*/
sbit Key_S2 = P0^1;
/*定义蜂鸣器*/
sbit BUZZER = P2^7;

unsigned char ucKeySec = 0;   /*被触发的按键编号*/

unsigned int  uiKeyTimeCnt1 = 0; /*按键去抖动延时计数器*/
unsigned char ucKeyLock1 = 0; /*按键触发后自锁的变量标志*/

unsigned int  uiKeyTimeCnt2 = 0; /*按键去抖动延时计数器*/
unsigned char ucKeyLock2 = 0; /*按键触发后自锁的变量标志*/

unsigned int  uiVoiceCnt = 0;  /*蜂鸣器鸣叫的持续时间计数器*/


/**
* @brief  定时器0初始化函数
* @param  无
* @retval 初始化T0
**/
void Init_T0(void)
{
	TMOD = 0x01;                    /*set timer0 as mode1 (16-bit)*/
	TL0 = T1MS;                     /*initial timer0 low byte*/
	TH0 = T1MS >> 8;                /*initial timer0 high byte*/
}
/**
* @brief  定时器0中断函数
* @param  无
* @retval 无
**/
void ISR_T0(void)	interrupt 1
{
	TF0 = 0;  /*清除中断标志*/
  TR0 = 0; /*关中断*/
	if(0 != uiVoiceCnt)
	{
		uiVoiceCnt --;
		BUZZER = 0;
	}
	else
	{
		BUZZER = 1;
	}
	
	TL0 = T1MS;                     /*initial timer0 low byte*/
	TH0 = T1MS >> 8;                /*initial timer0 high byte*/
  TR0 = 1; /*开中断*/	
}
/**
* @brief  外围初始化函数
* @param  无
* @retval 初始化外围
**/
void Init_Peripheral(void)
{
	ET0 = 1;/*允许定时中断*/
	TR0 = 1;/*启动定时中断*/
	EA = 1;/*开总中断*/

}

/**
* @brief  初始化函数
* @param  无
* @retval 初始化单片机
**/
void	Init(void)
{
	Init_T0();
	BUZZER = 1;
}
/**
* @brief  扫描按键函数
* @param  无
* @retval 独立按键扫描的详细过程:
* 第一步:平时没有按键被触发时,按键的自锁标志和去抖动延时计数器一直被清零。
* 第二步:一旦有按键被按下,去抖动延时计数器开始累加,在还没累加到
*         阀值const_key_time1时,如果在这期间由于受外界干扰或者按键抖动,而使
*         IO口突然瞬间触发成高电平,这个时候马上又把延时计数器uiKeyTimeCnt1
*         清零了,这个过程非常巧妙,非常有效地去除瞬间的杂波干扰。
*         以后凡是用到开关感应器的时候,都可以用类似这样的方法去干扰。
* 第三步:如果按键按下的时间超过了阀值const_key_time1,则触发按键,把编号ucKeySec赋值。
*         同时,马上把自锁标志ucKeyLock1置位,防止按住按键不松手后一直触发。
* 第四步:等按键松开后,自锁标志ucKeyLock1及时清零,为下一次自锁做准备。
* 第五步:以上整个过程,就是识别按键IO口下降沿触发的过程。
**/
void Key_Scan(void)
{
	/*扫描S1*/
	if(Key_S1 == 1)	/*如果没有键按下(高电平),将一些标志位及时清零*/
	{
		ucKeyLock1 = 0;/*自锁标志位清0*/
		uiKeyTimeCnt1 = 0;/*按键去抖动延时计数器清零*/
	}
	else if(ucKeyLock1 == 0)	/*如果有按键按下,且是第一次按下*/
	{
		++ uiKeyTimeCnt1;/*延时计数器计数*/
		if(uiKeyTimeCnt1 > const_key_time1)
		{
			uiKeyTimeCnt1 = 0;
			ucKeyLock1 = 1;/*自锁标志位置位,避免一直触发*/
			ucKeySec = 1; /*触发S1*/
		}
	}
	/*扫描S2*/
	if(Key_S2 == 1)	/*如果没有键按下(高电平),将一些标志位及时清零*/
	{
		ucKeyLock2 = 0;/*自锁标志位清0*/
		uiKeyTimeCnt2 = 0;/*按键去抖动延时计数器清零*/
	}
	else if(ucKeyLock2 == 0)	/*如果有按键按下,且是第一次按下*/
	{
		++ uiKeyTimeCnt2;/*延时计数器计数*/
		if(uiKeyTimeCnt2 > const_key_time2)
		{
			uiKeyTimeCnt2 = 0;
			ucKeyLock2 = 1;/*自锁标志位置位,避免一直触发*/
			ucKeySec = 2; /*触发S2*/
		}
	}	
	
}
/**
* @brief  按键服务函数
* @param  无
* @retval 根据扫描得到的值,进行数据处理
**/
void key_Service(void)
{
	switch(ucKeySec)
	{
		case 1: /*S1按下*/
				uiVoiceCnt = const_voice_short;  /*蜂鸣器短叫*/			
				ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/
		break;
		case 2:/*S2按下*/
				uiVoiceCnt = const_voice_short;  /*蜂鸣器短叫*/		
				ucKeySec = 0; 
		break;			
	}
}
/**
* @brief  延时函数
* @param  无
* @retval 无
**/
void Delay_Long(unsigned int uiDelayLong)
{
   unsigned int i;
   unsigned int j;
   for(i=0;i

三、仿真实现

单片机学习笔记————51单片机累计主循环次数实现独立按键_第2张图片

你可能感兴趣的:(proteus,单片机,C)