第三周 基于定时器的倒计时程序设计

/*头文件*/
#include <REGX52.H>
#include "Key.h"
#include "Seg.h"

/*变量声明区*/
unsigned char Key_Slow_Down;//按键减速专用变量 10ms
unsigned char Key_Val,Key_Down,Key_Old;//按键扫描变量
unsigned int Seg_Slow_Down;//数码管减速专用变量 500ms
unsigned char Seg_Pos;//数码管扫描变量
unsigned char Seg_Buf[6] = {10,10,10,10,10,10};//数码管显示数据储存数组
unsigned char Seg_Point[6] = {0,0,0,0,0,0};//数码管小数点数据存放数组
unsigned char Seg_Mode;//数码管界面专用变量 0-显示界面 1-设置界面
unsigned int Timer_1000Ms;//1000ms标志位
unsigned char Timer_Count = 30;//倒计时显示变量
unsigned char Timer_Data[3] = {15,30,60};//倒计时设置参数数组
unsigned char Timer_Data_Index = 1;//倒计时设置参数数组索引
bit System_Flag;//系统使能标志位 0-失能 1-使能

/*按键处理函数*/
void Key_Proc()
{
	if(Key_Slow_Down) return;
	Key_Slow_Down = 1;//按键减速程序
	
	Key_Val = Key_Read();//检测按下的键码值
	Key_Down = Key_Val & (Key_Val ^ Key_Old);//检测下降沿
	Key_Old = Key_Val;//辅助扫描
	
	//下降沿触发
	switch(Key_Down)
	{
		case 1://“开始”按键
			if(Seg_Mode == 0)//处于显示界面
				System_Flag = 1;
		break;
		case 2://“复位”按键
			Timer_Count = Timer_Data[Timer_Data_Index];
		break;
		case 3://“切换”按键
			Seg_Mode ^= 1;
			if(Seg_Mode == 0)//从设置界面切换到显示界面
				Timer_Count = Timer_Data[Timer_Data_Index];
		break;
		case 4://“设置”按键
			if(Seg_Mode == 1)//处于设置界面
			{
				if(++Timer_Data_Index == 3)
					Timer_Data_Index = 0;
			}
		break;
	}
}

/*显示处理函数*/
void Seg_Proc()
{
	if(Seg_Slow_Down) return;
	Seg_Slow_Down = 1;//数码管减速程序
	
	Seg_Buf[0] = Seg_Mode + 1;
	if(Seg_Mode == 0)//处于显示界面
	{
		Seg_Buf[4] = Timer_Count / 10 % 10;
		Seg_Buf[5] = Timer_Count % 10;
	}
	else//处于设置界面
	{
		Seg_Buf[4] = Timer_Data[Timer_Data_Index] / 10 % 10;
		Seg_Buf[5] = Timer_Data[Timer_Data_Index] % 10;
	}
	if(Seg_Buf[4] == 0)	Seg_Buf[4] = 10;
}

/*其他显示函数*/
void Led_Proc()
{
	if(Timer_Count == 0)
	{
		P1 = 0x00;
		P2_3 = 0;
	}
	else
	{
		P1 = 0xff;
		P2_3 = 1;
	}
}

/*定时器0初始化函数*/
void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0 = 1;
	EA = 1;
}


/*定时器0中断服务函数*/
void Timer0Server() interrupt 1
{
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//10ms循环
	if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;//500ms循环
	if(++Seg_Pos == 6) Seg_Pos = 0;//0-5循环
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);//数码管显示
	if(System_Flag == 1)//系统使能
	{
		if(++Timer_1000Ms == 1000)//倒计时
		{
			Timer_1000Ms = 0;
			Timer_Count--;
			if(Timer_Count == 255)
				Timer_Count = 0;
		}
	}
}

/*Mian*/
void main()
{
	Timer0_Init();
	while(1)
	{
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}