一、主要功能

此设计是在数码管上显示时、分、秒,电路包括:键盘、单片机及显示电路。

各部分说明:

(1) 键盘用于校正、调节数码管上显示的时间。

(2) 单片机通过输出各种电脉冲信号开驱动控制各部分正常工作。

(3) 单片机发送的信号经过显示电路通过译码最终在数码管上显示出来。

(4) 整点或半点蜂鸣器响,小灯整点闪10下,半点的时候闪5下。

本设计采用STC89C51单片机作为主控制器,外部加上74HC573驱动数码管。系统总体框图如下:

基于单片机的简易声光报时时钟_单片机

二、简易时钟的工作流程

系统工作过程:时间的主要处理过程是在CPU中完成的。CPU会随时对时间进行读取数据的操作。在读取了相应的寄存器的值后,CPU将读取的值进行处理,再通过I/O口把数据显示在数码管上。

基于单片机的简易声光报时时钟_单片机_02

三、简易时钟的优点

1. 高精度

单片机简易时钟使用晶振作为时钟源,具有高精度、稳定的特性。因此,在需要高精度计时的应用场合中,单片机简易时钟是一个非常好的选择。

2. 灵活性

单片机简易时钟可以通过程序改变产生频率和工作模式,以适应不同的应用需求。同时,它也可以通过编程来实现更复杂的功能,例如报警、闹钟、定时等。

3. 可扩展性

单片机简易时钟通常具有丰富的输入输出接口,可以与其他设备进行通讯,并实现更广泛的应用。例如,可以通过网络连接实现远程控制和集成,也可以与传感器结合使用来监测环境参数并自动调整系统。

4. 安全性

单片机简易时钟的工作过程由程序控制,可以实现各种安全保护措施,例如自动断电、自动重启、密码保护等。这些措施可以确保系统的稳定性和安全性。

5. 便携性

单片机简易时钟通常体积小、重量轻,可以方便地集成到各种设备中。例如,可以将其嵌入手表、闹钟等物品中,以实现时间显示和报警功能。

总之,单片机简易时钟具有高精度、灵活性、可扩展性、安全性和便携性等特点,适用于许多应用场合。

四、总体原理图

基于单片机的简易声光报时时钟_初值_03

五、时钟频率电路的设计

STC89C51单片机的时钟信号通常有两种方式产生:一是内部时钟方式,二是外部时钟方式。内部时钟方式如图2-4所示。在STC89C51单片机内部有一振荡电路,只要在单片机的XTAL1(18)和XTAL2(19)引脚外接石英晶体(简称晶振),就构成了自激振荡器并在单片机内部产生时钟脉冲信号。图中电容C1和C2的作用是稳定频率和快速起振,电容值在5~30pF,典型值为30pF。晶振CYS的振荡频率范围在1.2~12MHz间选择,典型值为12MHz和6MHz。

基于单片机的简易声光报时时钟_初值_04

六、复位电路的设计

当在STC89C51单片机的RST引脚引入高电平并保持2个机器周期时,单片机内部就执行复位操作(若该引脚持续保持高电平,单片机就处于循环复位状态)。

复位电路通常采用上电自动复位和按钮复位两种方式。

最简单的上电自动复位电路中上电自动复位是通过外部复位电路的电容充放电来实现的。只要Vcc的上升时间不超过1ms,就可以实现自动上电复位。

除了上电复位外,有时还需要按键手动复位。本设计就是用的按键手动复位。按键手动复位有电平方式和脉冲方式两种。其中电平复位是通过RST(9)端与电源Vcc接通而实现的。按键手动复位电路见图5。时钟频率用11.0592MHZ时C取10uF,R取10kΩ。

基于单片机的简易声光报时时钟_单片机_05

七、软件功能模块
1.控制器模块

方案1:采用51系列作为系统控制器

单片机算术运算功能强,软件编程灵活、自由度大,可用软件编程实现各种算法和逻辑控制。由于其功耗低、体积较小、技术成熟和成本低等优点,在各个领域应用广泛。而且抗干扰性能好。

方案2:采用凌阳系列单片机为系统的控制器

凌阳系列单片机可以实现各种复杂的逻辑功能,模块大,密度高,它将所有器件集成在一块芯片上,减少了体积,提高了稳定性。凌阳系列单片机提高了系统的处理速度,适合作为大规模实时系统的控制核心。

因51单片机价格比凌阳系列低得多,且本设计不需要很高的处理速度,从经济和方便使用角度考虑,本设计选择了方案1。

2.计时模块

数字时钟是本设计的最主要的部分。根据需要,可利用两种方案实现。

方案一:本方案采用Dallas公司的专用时钟芯片DS12C887。该芯片内部采用石英晶体振荡器,其芯片精度不大于10ms/年,且具有完备的时钟闹钟功能,因此,可直接对其以用于显示或设置,使得软件编程相对简单。为保证时钟在电网电压不足或突然掉电等突发情况下仍能正常工作,芯片内部包含锂电池。当电网电压不足或突然掉电时,系统自动转换到内部锂电池供电系统。而且即使系统不上电,程序不执行时,锂电池也能保证芯片的正常运行,以备随时提供正确的时间。

方案二:本方案完全用软件实现数字时钟。原理为:在单片机内部存储器设三个字节分别存放时钟的时、分、秒信息。利用定时器与软件结合实现1秒定时中断,每产生一次中断,存储器内相应的秒值加1;若秒值达到60,则将其清零,并将相应的分字节值加1;若分值达到60,则清零分字节,并将时字节值加1;若时值达到24,则将十字节清零。该方案具有硬件电路简单的特点。但由于每次执行程序时,定时器都要重新赋初值,所以该时钟精度不高。而且,由于是软件实现,当单片机不上电,程序不执行时,时钟将不工作。

基于硬件电路的考虑,本设计采用方案二完成数字时钟的功能。

3.显示模块

方案1:采用LED数码管

显示用LED数码管。虽然显示的内容有限,但是也可以显示数字和几个英文字母,在此设计中已经足够了,并且价格比液晶字符式要低的多,为了降低设计制作的成本,在此设计中我们选用LED数码管显示。

方案2:采用液晶字符显示器

显示用液晶,可以用软件达到很好的控制,硬件不复杂,液晶字符显示器可以显示很丰富的内容,显示清晰,但是液晶字符式价格昂贵,在本设计中不需要用到复杂的显示内容,因此我们放弃了此方案。

从经济的角度考虑,我们选择了方案1。

八、软件KEIL5功能的实现

基于单片机的简易声光报时时钟_单片机_06

主要程序代码:
void delay(ui x)//1ms延时函数
{
	ui i,j;
	for(i=0;i<x;i++)
	for(j=0;j<121;j++);
}
void display()//扫描显示函数,高位到低位
{
	P0=tab[hour/10];//给小时的十位送形
	P2=0xdf;//11011111 //位选
	delay(1); //延时动态扫描
	P2=0xff;  //关闭位选

	P0=(tab[hour%10])|0x80;//给第二位后加“点
	P2=0xef;//11101111
	delay(1);
	P2=0xff;

	P0=tab[min/10];
	P2=0xf7;//11110111
	delay(1);
	P2=0xff;

	P0=(tab[min%10])|0x80;//给第四位后加“点”
	P2=0xfb;//11111011
	delay(1);
	P2=0xff;

	P0=tab[sec/10];
	P2=0xfd;//11111101
	delay(1);
	P2=0xff;

	P0=tab[sec%10];
	P2=0xfe;//11111110
	delay(1);
	P2=0xff;
}

void keyscan()//键盘扫描,开关接地
{
	if(key1==0)	 //如果小时加按键按下
	{
		delay(5);  //延时去抖
		if(key1==0)	 //确定是否按键
		{
			hour++;	 //小时加一
			if(hour==24) //如果小时等于24
			hour=0;		//小时归零
		}
		while(!key1) display();//判断是否松开
	}
	if(key2==0)	  //如果分钟加按键按下
	{
		delay(5);  //延时去抖
		if(key2==0)	//确定是否按键
		{
			min++; //分钟加一
			if(min==60)// 如果分钟等于60
			min=0;	//分钟归零
		}
		while(!key2) display();//判断是否松开
	}
	if(key3==0)//判断调整秒按键
	{
		delay(5);  //延时去抖
		if(key3==0)	//确定是否按键
		{sec=0;} //秒清零
		while(!key3) display();//判断是否松开
	}
}
void strike()//报时函数
{
	if((hour>6)&&(hour<22))//判断大于6点并且小于22点
	{
		if(sec==0)//以下判断是否整点
		{
			if(min==0)//如果秒和分都等于0
			{
				hourbeep=1;	//那么蜂鸣器和小灯位开启
				hourLED=1;
			}
			else if(min==30)//如果分钟等于30
			{
				if(num<10)	//闪5下响一声
				halfbeep=1;
				halfLED=1;
			}
		}
	}
	else //小于6点和大于22点的时候
	{
		if(sec==0)//以下判断是否整点
		{
			if(min==0)//如果分钟等于0
			hourLED=1; //led位开
			else if(min==30)//如果分钟=0
			halfLED=1;//进行半点报时
		}
	}
}

void init()//初始化函数
{
	sec=0;//一通电,显示12:30:00,蜂鸣器响一下
	min=30;
	hour=12;
	TMOD=0x01;//设置定时器为定时器0工作方式为1
	TH0=(65536-50000)/256;	//赋初值
	TL0=(65536-50000)%256;  //赋初值
	EA=1; //开总中断
	ET0=1; //开定时器0中断
	TR0=1; //启动定时器0
}

void main()//主函数
{
	init();//初始化
	while(1) //主循环
	{
		display(); //显示
		keyscan();//扫描是否有键按下
		strike();//报时函数
	}
}
void time0() interrupt 1  //定时器中断
{
	TH0=(65536-50000)/256;//重赋初值
	TL0=(65536-50000)%256;//重赋初值
	num++;
	if((num%10==0)&&(hourLED==1)) //整点报时
	{
		led++;
		LED=~LED;//取反实现闪烁
		if(led==20)	//闪10次
		{
			led=0;	//之后关闭闪烁
			LED=1;
			hourLED=0;
		}
	}
	else if((num%10==0)&&(halfLED==1))//半点报时
	{
		led++;
		LED=~LED; //取反实现闪烁
		if(led==10)//闪5次
		{
			led=0; //关闭闪烁
			LED=1;
			halfLED=0;
		}
	}
	if(hourbeep==1)	//蜂鸣器响标志位
	{
		if(num==1)
		beep=0;
		if(num==20)	 //长响次之后
		{
			beep=1;	  //关闭
			hourbeep=0;
		}
	}
	else if(halfbeep==1) //蜂鸣器响标志位
	{
		if(num<10)
		beep=0;
		if(num==10)	 //短响之后
		{
			beep=1;	 //关闭
			halfbeep=0;
		}
	}
	if(num==20)	//计时20次为1s时间
	{
		num=0;	
		sec++;	//秒加一
		if(sec==60)//如果秒等于60
		{
			sec=0; //秒归零
			min++; //分钟加一
			if(min==60)//如果分钟等于60
			{
				min=0; //分钟归零
				hour++;	//小时加一
				if(hour==24) //如果小时等于24
				{hour=0;}//小时归零
			}
		}
	}
}
九、Proteus仿真结果测试

基于单片机的简易声光报时时钟_初值_07