Bootstrap

基于51单片机的简易时钟设计(实验)

1.设计内容

以单片机为核心,设计一个电子时钟,能分别显示“时-分-秒”1.显示范围从0小时0分0秒到23小时59分59秒,通过定时器实现定时1s,实现时分、秒的运行及显示。
2.可通过键盘设置小时、分钟和秒数的初值。
3.当调时按键按下后,进入调整时间模式,通过按键进行新一次时间调整。
4.当按下 24-12 进制切换按键后,时钟显示会在 24时制和 12时制之间切换。

2.简易原理图(Proteus仿真)

原理图仿真采用的共阳极数码管(7SEG-MPX8-CA-BLUE)

图1

图2

按键介绍

P3_0按键,在时间调整界面用于调整时、分、秒的

P3_1按键,在时间调整界面用于调整时、分、秒的

P3_2按键,当在时钟显示界面时(如图1),按键按下后,进入时间调整模式,被调整的时间会进入闪烁状态,通过按键不断进行依次调整时、分、秒。当在进制切换界面时(如图2),按键按下后,用于24时制和 12时制之间的切换。

P3_4按键,按下后会进入时钟的进制调整界面,时钟显示会在 24时制和 12时制之间切换,前两位显示此刻的小时显示,后两位显示此时的时钟进制。

参考代码
#include <REGX51.H>
/* 底层函数声明区域 */
void Seg_Disp(unsigned char wela,dula);
unsigned char Key_Read();
/* 变量声明区 */
unsigned char Key_Val,Key_Down,Key_Old,Key_Up;//按键专用变量
unsigned char Key_Slow_Down;//按键减速专用变量
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};//数码管显示数据存放数组
unsigned char Seg_Pos;//数码管扫描专用变量
unsigned int Seg_Slow_Down;//数码管减速专用变量
unsigned char seg_disp_mode;//0-时钟界面 1-切换界面

unsigned int TCount;//1s计时变量
unsigned char Time[4] = {18,59,51};//时钟存放数组
unsigned char Time_index;//数组指针
unsigned char Tab = 24;//用于12-24切换
bit star_flag;//闪烁标志位
/* 键盘处理函数 */
void Key_Proc()
{
	if(Key_Slow_Down) return;
	Key_Slow_Down = 1;//键盘减速程序
	Key_Val = Key_Read();//实时读取键码值
	Key_Down = Key_Val & (Key_Old ^ Key_Val);//捕捉按键下降沿
	Key_Up = ~Key_Val & (Key_Old ^ Key_Val);//捕捉按键上降沿
	Key_Old = Key_Val;//辅助扫描变量

	switch(Key_Down)
	{
		case 4://+
			if(Time_index != 0)
				Time[Time_index-1]++;
		break;
		case 5://-
			if(Time_index != 0)
				Time[Time_index-1]--;
		break;
		case 6://调整
			if(seg_disp_mode == 0)
			{
				if(++Time_index >= 4)
				Time_index = 0;
			}else{
			   if(Tab == 24)
				{
					Tab = 12;
					if(Time[0] > 12)Time[0] -= 12;
					else if(Time[0] ==0) Time[0] = 12;
				}else if(Tab == 12)
				{
					Tab = 24;
					if(Time[0] < 12 && Time[0] > 0)Time[0] += 12;	
				}
			}
		break;
		case 7://切换
			if(++seg_disp_mode == 2) {seg_disp_mode = 0;}
		break;
	}
}
/* 信息处理函数 */
void Seg_Proc()
{
	unsigned char i;
	if(Seg_Slow_Down) return;
	Seg_Slow_Down = 1;//数码管减速程序
	if(Time[2] >= 60){Time[2] = 0; Time[1]++;}
	if(Time[1] >= 60){Time[1] = 0; Time[0]++;}
	if(Tab == 24){if(Time[0] >= Tab) Time[0] = 0;}
	else{if(Time[0] > Tab) Time[0] = 1;}
	
	if(seg_disp_mode == 0)
	{
		Seg_Buf[2] = Seg_Buf[5] = 11;//-
		for(i=0;i<3;i++)
		{
			Seg_Buf[3*i] = Time[i] / 10 % 10;
			Seg_Buf[3*i+1] = Time[i] % 10;
		}
		if(Time_index != 0)
		{
			Seg_Buf[3*(Time_index-1)] = star_flag?10:Time[Time_index-1] / 10;
			Seg_Buf[3*(Time_index-1)+1] = star_flag?10:Time[Time_index-1] % 10;
		}
	}else{
		for(i=2;i<6;i++)
		{
			Seg_Buf[0] = Time[0] / 10;
			Seg_Buf[1] = Time[0] % 10;
			Seg_Buf[i] = 10;
			Seg_Buf[6] = Tab / 10;
			Seg_Buf[7] = Tab % 10;
		}	
	}
	//
	
}
/* 定时器0中断初始化函数 */
void Timer0Init(void)		//1毫秒@12.000MHz
{
	TMOD |= 0X01;
	TL0 = 0x18;		//设置定时初始值
	TH0 = 0xFC;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时	
	ET0 = 1;    //定时器中断0打开
	EA = 1;     //总中断打开
}
/* 定时器0中断服务函数 */
void Timer0Server() interrupt 1
{
	TL0 = 0x18;		//设置定时初始值
	TH0 = 0xFC;		//设置定时初始值
	TCount++;
	if(TCount>=1000)
	{
		TCount=0;
		Time[2]++;
	}
	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//键盘减速专用
	if(++Seg_Slow_Down == 350) {Seg_Slow_Down = 0;star_flag ^= 1;}//数码管减速专用
	if(++Seg_Pos == 8) Seg_Pos = 0;//数码管显示专用
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]);
}
/* Main */
void main()
{
	Timer0Init();
	while (1)
	{
		Key_Proc();
		Seg_Proc();
	}
}
/* 底层函数 */
unsigned char seg_dula[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};
unsigned char seg_wela[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
void Seg_Disp(unsigned char wela,dula)
{
	P0 = 0xff;
	P2 = seg_wela[wela];
	P0 = seg_dula[dula];	
}
unsigned char Key_Read()
{
	unsigned char temp = 0;
	if(P3_0 == 0) temp = 4;
	if(P3_1 == 0) temp = 5;
	if(P3_2 == 0) temp = 6;
	if(P3_3 == 0) temp = 7;
	return temp;
}

;