基于51单片机的可调时钟和闹钟(STC15F2K60S2)

(一)概述

开发板是蓝桥杯的开发版,主控芯片是IAP15FK60S2,不是89C52,是看着江科大的视频学的.主要是很多文章都是89C52的,没有15FK60S2的,所以就有了这篇,也当是练练手.

显示用的是数码管不是LCD1602,买蓝桥杯板子的时候可没配有1602,用数码管确实会复杂许多,没有买液晶屏的朋友可能看着视频学起来比较难受,包括有相当一部分东西和89C52是不一样的,比如说想把代码直接写进去运行都不行.

江科大视频的时钟是按下1后选择设置时间还是显示时间,按下2后选择设置年月日时分秒中的哪一位,按3 是增加,4是减少.

但是用数码管显示的话,首先年月日时分秒就要分成两部分显示,需要一个按键切换,我用了按键4;选择设置年月日还是时分秒,我用了按键5;选择设置哪一位需要一个按键,我用了按键6;增加我用了按键7,减少我用了按键8.越界判断没有变,我只是用了一些switch改写,相当牛逼的判断.9是确认键.

值得一提,这里使用的数码管和按键都是后面讲过的定时器扫描.标志位闪烁的实现是通过在定时器每隔500ms翻转一次闪烁标志变量,然后在设置数码管显示的函数调用时通过三目运算符判断是显示值还是什么都不显示.

此外,我还为这个时钟系统添加了闹钟功能,在按键10选择设置闹钟后,使用和调时间同样的按键调闹钟即可,按键11是取消或关闭闹钟;按键12是把上次闹钟值在设置界面显示.按键13是关闭或打开按键声音.

如果觉得前面的话看着繁琐,文末有这个时钟系统的说明书

(二)代码

main.c

值得注意的是,在while中使用if判断成立再执行数码管设置函数会导致数码管显示不了,所以我采用了if判断后设置标志位,然后switch根据标志位选择显示的内容.

#include 
unsigned char mode1,mode2,mode,value,i;
unsigned char viewflag,flashflag1=1,flashflag2=1,flashflag3=1;
unsigned char vioceflag=0,alarmflag=0,soundflag=0,numberfeedback=0,ringflag=0;
char time[]={30,58,17,31,1,3,24},time3[7]={0,0,15,31,7,5,21},time4[7]={0,0,18,30,1,7,24},time5[7];//初始时间
void timeset()//选择调的时间
{ 
		switch(mode2)
		{
			case 0://调时分秒
				viewflag=6;
				break;
				
			case 1://调年月日
				viewflag=7;
				break;
		}
}

void timeshow(unsigned char i)//读取当前时间显示
{
	readTime0();
	switch(i)
	{
		
		case 0://时分秒
			smg_set(0,time1[2]);
			smg_set(1,time0[2]);
			smg_set(2,16);
			smg_set(3,time1[1]);
			smg_set(4,time0[1]);		
			smg_set(5,16);
			smg_set(6,time1[0]);
			smg_set(7,time0[0]);
			break;
		
		case 1://年月日
			smg_set(0,time1[6]);
			smg_set(1,time0[6]);
			smg_set(2,16);
			smg_set(3,time1[4]);
			smg_set(4,time0[4]);		
			smg_set(5,16);
			smg_set(6,time1[3]);
			smg_set(7,time0[3]);	
			break;
	}
}

void timeget()//把当前时间写入设置界面
{
	for(i=0;i<7;i++)
	{
		time[i]=time0[i]+time1[i]*10;					
	}
}

void alarm()//对比现在时间和设置时间
{
	unsigned char buzzflag=1;
	static unsigned int k=0;
	for(i=0;i<7;i++)
		{
			time4[i]=time0[i]+time1[i]*10;			
		}
	for(i=0;i<7;i++)
	{
		if(time4[i]!=time3[i])
		{
			buzzflag=0;
			break;
		}
	}
	if(buzzflag==1)
	{
		ringflag=1;
	}
	if(soundflag==1&&ringflag==1)
	{
		P2andP1(0xA0,0x40,0);
		k++;
	}
	if(k>20000)//响一段时间可以自动关
	{
		k=0;
		ringflag=0;
		P2andP1(0x80,0xFF,0);
	}
}

void view()//数码管显示内容选择
{
	switch(viewflag)
		{
			case 0://上电就显示时分秒
				timeshow(0);
				break;
			
			case 4://控制显示时分秒还是年月日
				if(mode1==0)timeshow(0);
				if(mode1==1)timeshow(1);
				break;
			
			case 6://调时分秒时显示时分秒
				smg_set(0,(flashflag3==0)?17:time[2]/10);
				smg_set(1,(flashflag3==0)?17:time[2]%10);

				smg_set(2,16);
				smg_set(3,(flashflag2==0)?17:time[1]/10);
				smg_set(4,(flashflag2==0)?17:time[1]%10);
				
				smg_set(5,16);
				smg_set(6,(flashflag1==0)?17:time[0]/10);
				smg_set(7,(flashflag1==0)?17:time[0]%10);
				
				break;
			
			case 7://调年月日时显示年月日
				smg_set(0,(flashflag3==0)?17:time[6]/10);
				smg_set(1,(flashflag3==0)?17:time[6]%10);
				smg_set(2,16);
				smg_set(3,(flashflag2==0)?17:time[4]/10);
				smg_set(4,(flashflag2==0)?17:time[4]%10);		
				smg_set(5,16);
				smg_set(6,(flashflag1==0)?17:time[3]/10);
				smg_set(7,(flashflag1==0)?17:time[3]%10);
				break;							
		}
}

void voice()//按键声音
{
	vioceflag=1;
	if(vioceflag==1&&numberfeedback==0)P2andP1(0xA0,0x40,0);
}

void main()//初始化和按键逻辑判断
{
	P2andP1(0xA0,0,0);//关闭蜂鸣器继电器
	Timer0_Init();//定时器0初始化(1ms)
	init_ds1302();//1302初始化
	setTime0();//设置初始时间
	while(1)
	{	
		value=Keys();			
		switch(value) //按键功能控制
		{
			case 4://选择显示的时间是年月日还是时分秒
				voice();
				mode1++;
				mode1=mode1%2;
				viewflag=4;
				break;
			
			case 5://选择需要设置的时间
				voice();
				mode2++;
				mode2=mode2%2;
				viewflag=5;	
				timeset();
				break;
			
			case 6://选择设置时分秒还是年月日
				voice();
				if(viewflag==6||viewflag==7)
				{
					mode++;
					mode=mode%3;
				}
				break;
				
			case 7://+				
				voice();
				if(viewflag==6)
				{
					switch(mode)
					{
						case 0://控制秒
							time[0]++;
							if(time[0]>59)time[0]=0;
							break;
						
						case 1://控制分
							time[1]++;
							if(time[1]>59)time[1]=0;
							break;
						
						case 2://控制时
						time[2]++;	
						if(time[2]>23)time[2]=0;
							break;
					}
				}	
				if(viewflag==7)//+
				{
					switch(mode)
					{
						case 0://控制日
							time[3]++;
							if(time[4]==1||time[4]==3||time[4]==5||time[4]==7||time[4]==8||time[4]==10||time[4]==12)
							{
								if(time[3]>31)time[3]=1;
							}
							else if(time[4]==4||time[4]==6||time[4]==9||time[4]==11)
							{
								if(time[3]>30)time[3]=1;
							}
							else if(time[4]==2)
							{
								if(time[6]%4==0)
								{
									if(time[3]>29)time[3]=1;
								}
								else 
									if(time[3]>28)time[3]=1;			
							}
							break;
						
						case 1://控制月
							time[4]++;
							if(time[4]>12)time[4]=1;
							break;
						
						case 2://控制年
						time[6]++;	
						if(time[6]>99)time[6]=0;
							break;
					}
				}
				break;			
			
			case 8:
				voice();
				if(viewflag==6)
				{
					switch(mode)
					{
						case 0://控制秒
							time[0]--;
							if(time[0]<0)time[0]=59;
							break;
						
						case 1://控制分
							time[1]--;
							if(time[1]<0)time[1]=59;
							break;
						
						case 2://控制时
							time[2]--;
							if(time[2]<1)time[2]=23;
							break;
					}
				}
				if(viewflag==7)//-
				{
					switch(mode)
					{
						case 0://控制日
							time[3]--;
							if(time[4]==1||time[4]==3||time[4]==5||time[4]==7||time[4]==8||time[4]==10||time[4]==12)
							{
								if(time[3]<1)time[3]=31;
								if(time[3]>31)time[3]=1;
							}
							else if(time[4]==4||time[4]==6||time[4]==9||time[4]==11)
							{
								if(time[3]<1)time[3]=

你可能感兴趣的:(STC15F2K60S2,51单片机,嵌入式硬件,单片机,c语言,蓝桥杯)