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

/*头文件*/
#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,1,0,1,0,1};//数码管小数点数据存放数组
unsigned char Seg_Mode;//数码管显示界面 0-时钟显示界面 1-时钟设置界面 2-闹钟设置界面
unsigned char Clock_Disp[3] = {23,59,55};//时钟显示数组
unsigned char Clock_Set_Data[3] = {23,59,55};//时钟设置数组
unsigned char Alarm_Set_Data[3] = {0,0,0};//闹钟设置数组
unsigned char Alarm_Disp_Data[3] = {0,0,0};//闹钟设置数组
unsigned char Clock_Set_Data_Index;//时钟设置数组索引
unsigned int Timer_500Ms;//500ms标志位
unsigned int Timer_1000Ms;//1000ms标志位
bit Seg_Flag;//数码管闪烁标志位
bit Alarm_Enable_Flag;//闹钟使能标志位 0-使能
bit Led_Flag;//Led标志位
bit Alarm_Time_Flag;//用于判断上下午

/*按键处理函数*/
void Key_Proc()
{
	unsigned char i;//用于for循环
	
	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;//辅助扫描
	
	if(Key_Down != 0)//按下任意键
		Led_Flag = 0;
	
	//下降沿触发
	switch(Key_Down)
	{
		case 1://时钟设置按键
			if(Seg_Mode == 0)//处于时钟显示界面
			{
				Seg_Mode = 1;//进入时钟设置界面
				for(i=0;i<3;i++)
					Clock_Set_Data[i] = Clock_Disp[i];
				Clock_Set_Data_Index = 0;
			}
		break;
		case 2://闹钟设置按键
			if(Seg_Mode == 0)//处于时钟显示界面
			{
				Seg_Mode = 2;//进入闹钟设置界面
				for(i=0;i<3;i++)
						Alarm_Disp_Data[i] = Alarm_Set_Data[i];
				Clock_Set_Data_Index = 0;
			}
		break;
		case 3://设置切换按键
			if((Seg_Mode == 1) || (Seg_Mode == 2))//处于时钟设置界面或闹钟设置界面
			{
				if(++Clock_Set_Data_Index == 3)
					Clock_Set_Data_Index = 0;
			}
		break;
		case 4://闹钟功能按键
			Alarm_Enable_Flag ^= 1;
		break;
		case 5://参数+按键
			if(Seg_Mode == 1)//处于时钟设置界面
			{
				if(++Clock_Set_Data[Clock_Set_Data_Index] == (Clock_Set_Data_Index?60:24))
					Clock_Set_Data[Clock_Set_Data_Index] = 0;
			}
			else if(Seg_Mode == 2)//处于闹钟设置界面
			{
				if(++Alarm_Disp_Data[Clock_Set_Data_Index] == (Clock_Set_Data_Index?60:24))
					Alarm_Disp_Data[Clock_Set_Data_Index] = 0;
			}
		break;
		case 6://参数-按键
			if(Seg_Mode == 1)//处于时钟设置界面
			{
				if(--Clock_Set_Data[Clock_Set_Data_Index] == 255)
					Clock_Set_Data[Clock_Set_Data_Index] = Clock_Set_Data_Index?59:23;
			}
			else if(Seg_Mode == 2)//处于闹钟设置界面
			{
				if(--Alarm_Disp_Data[Clock_Set_Data_Index] == 255)
					Alarm_Disp_Data[Clock_Set_Data_Index] = Clock_Set_Data_Index?59:23;
			}
		break;
		case 7://确认按键
			if(Seg_Mode == 1)//处于时钟设置界面
			{
				for(i=0;i<3;i++)
					Clock_Disp[i] = Clock_Set_Data[i];
				Seg_Mode = 0;
			}
			else if(Seg_Mode == 2)//处于闹钟设置界面
			{
				for(i=0;i<3;i++)
					Alarm_Set_Data[i] = Alarm_Disp_Data[i];
				Seg_Mode = 0;
			}
		break;
		case 8://退出按键
				Seg_Mode = 0;
		break;
	}
}

/*显示处理函数*/
void Seg_Proc()
{
	unsigned char i;//用于for循环
	if(Seg_Slow_Down) return;
	Seg_Slow_Down = 1;//数码管减速程序
	
	switch(Seg_Mode)
	{
		case 0://时钟显示界面 
			for(i=0;i<3;i++)
			{
				Seg_Buf[2*i] = Clock_Disp[i] / 10 % 10;
				Seg_Buf[1+2*i] = Clock_Disp[i] % 10;
			}
		break;
		case 1://时钟设置界面 
			for(i=0;i<3;i++)
			{
				Seg_Buf[2*i] = Clock_Set_Data[i] / 10 % 10;
				Seg_Buf[1+2*i] = Clock_Set_Data[i] % 10;
			}
			Seg_Buf[2*Clock_Set_Data_Index] = Seg_Flag?Clock_Set_Data[Clock_Set_Data_Index] / 10 % 10:10;
			Seg_Buf[1+2*Clock_Set_Data_Index] = Seg_Flag?Clock_Set_Data[Clock_Set_Data_Index] % 10:10;
		break;
		case 2://闹钟设置界面 
			for(i=0;i<3;i++)
			{
				Seg_Buf[2*i] = Alarm_Disp_Data[i] / 10 % 10;
				Seg_Buf[1+2*i] = Alarm_Disp_Data[i] % 10;
			}
			Seg_Buf[2*Clock_Set_Data_Index] = Seg_Flag?Alarm_Disp_Data[Clock_Set_Data_Index] / 10 % 10:10;
			Seg_Buf[1+2*Clock_Set_Data_Index] = Seg_Flag?Alarm_Disp_Data[Clock_Set_Data_Index] % 10:10;
		break;
	}
}

/*其他显示函数*/
void Led_Proc()
{
	
	if(Alarm_Enable_Flag == 0 && Clock_Disp[0] == Alarm_Set_Data[0] && Clock_Disp[1] == Alarm_Set_Data[1] && Clock_Disp[2] == Alarm_Set_Data[2])//闹钟开启
		Led_Flag = 1;
	if (Led_Flag) 
	{
			if (Clock_Disp[0] < 12)  // 上午:前4个闪烁
					P1 = Seg_Flag?0xf0:0xff;
			else             // 下午:后4个闪烁
					P1 = Seg_Flag?0x0f:0xff;
			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(++Timer_1000Ms == 1000)//时钟程序
	{
		Timer_1000Ms = 0;
		if(++Clock_Disp[2] == 60)
		{
			Clock_Disp[2] = 0;
			if(++Clock_Disp[1] == 60)
			{
				Clock_Disp[1] = 0;
				if(++Clock_Disp[0] == 24)
					Clock_Disp[0] = 0;
			}
		}
	}
	if(++Timer_500Ms == 500)//闪烁程序
	{
		Timer_500Ms = 0;
		Seg_Flag ^= 1;
	}
}

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