51单片机基础07 实时时钟-思路及代码参考1

目录

一、实现功能

二、思路1的分析

1、定时器0

2、外部中断0

3、主函数main

4、其他重要功能函数


一、实现功能

1、实现最基本的计时功能,显示时、分、秒,可以通过按键设置时间。

要求:时钟计时精确,按键操作不影响计时。

2、具备秒表计时功能。

要求:记时精度达到100ms,计时支持启动、暂停、继续和停止操作。

3、具备整点响铃提示功能。

要求:整点闹铃五短一长,闹钟响铃时可以按键清楚响铃。

4、具备日期显示和调整功能。

二、思路1的分析

1、定时器0

进行时分秒的递增与计算,其中定时器0的采用了16位的50ms定时,

cpp 复制代码
void T0_ISR(void) interrupt 1
{
	uchar i=0;
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	
	if(time_flag==0)
	{
		count++;
		if(count==20)
		{
			count=0;
			miao++;
		}
		if(miao==60)
		{
			miao=0;
			fen++;
		}
		if(fen==60)
		{
			fen=0;
			shi++;
		}
		if(shi==24)
		{
			shi=0;
		} 
		if(shi!=0)
		if(fen==0)
		if(miao==0)
		beep_flag=1;
	}
	else 
	{
		if(TIME_CONTROL==0)
		{
			Timing++;
			if(Timing==2)
			{
				Timing=0;
				TIME_CLK++;
			}
		}
	}
}

2、外部中断0

实现按键触控实现调整时分秒、秒表定时设定、日期调整设定。当然受限于屏幕大小,可以通过按键调整当前显示的功能。

即按下KEY1,实现DATA-CLK,即从日期显示改为时间显示,或从时间显示切换为日期显示。

即按下KEY2,实现CLK-TIMING,即从时间显示改为定时,或从定时切换为时间显示。

前文提到过,外部定时只有一个,除了上述两个按键,还有年月日、时分秒、开始暂停等调整,如何都实现外部中断呢。

可以看到通过两级与非门,实现了所有按键最后接到了外部中断,同时每个引脚再分别接到IO上,从而实现任意一个按键按下都会进入中断,在中断中再进行判断哪个按键被按下。

cpp 复制代码
void keyscan()
{
	if(key1==0)
	{
		delay_ms(10);
		if(key1==0);
		{
			shi++;
		}
	}
	if(key2==0)
	{
		delay_ms(10);
		if(key2==0)
		{
			fen++;
		}
	}
	if(key3==0)
	{
		delay_ms(10);
		if(key3==0)
		{
			miao++;
		}
	}
	if(key4==0)
	{
		delay_ms(10);
		if(key4==0)
		{
			BEEP_Control=0;;
		}
	}
	if(key5==0)
	{
		delay_ms(10);
		if(key5==0)
		{
			time_flag=~time_flag;	
			lcd_clr();
			delay_ms(10);
			lcd_clr();
		}
	}
	if(key6==0)
	{
		delay_ms(10);
		if(key6==0)
		{
			TIME_CONTROL=~TIME_CONTROL;
			lcd_clr();
			delay_ms(10);
			lcd_clr();
		}
	}
	if(key7==0)
	{
		delay_ms(10);
		if(key7==0)
		{
			date_CONTROL=~date_CONTROL;
			lcd_clr();
			delay_ms(10);
			lcd_clr();
		}
	}
	if(key8==0)
	{
		delay_ms(10);
		if(key8==0)
		{
			ri++;
		}
	}
	if(key9==0)
	{
		delay_ms(10);
		if(key9==0)
		{
			yue++;
		}
	}
	if(key10==0)
	{
		delay_ms(10);
		if(key10==0)
		{
			nian++;
		}
	}				
}
void INT0_ISR(void) interrupt 0
{
	EX0=0;
	delay_ms(1);
	if(0==P3_2)
	{
 	    keyscan();
	}
	IE0=0;
	EX0=1;
}

3、主函数main

循环刷新LCD显示时分秒、秒表、日期。

cpp 复制代码
void api()
{
	uchar i=0;
	if(date_CONTROL==0)
	{
		TIME_CLK=0;
		shi=fen=miao=0;
	    date_display();
	    for(i=0;i<8;i++)
	    {
		    lcd_wcom(0x8B+i);   
		    lcd_wdat(table5[i]); 
	    }	
	}
	else
	{
		if(time_flag==0)
		{
			TIME_CLK=0;
			if(beep_flag==1)
			{
			   beep_flag=0;
			   beep_on();
			}
			time_display();
			for(i=0;i<7;i++)
			{
				lcd_wcom(0x88+i);   
				lcd_wdat(table1[i]); 
			}
		}
		else  
		{
			timing_display();
			if(TIME_CONTROL==0)
			{
			  shi=fen=miao=0;
			  for(i=0;i<11;i++)
				{
					lcd_wcom(0x86+i);   
					lcd_wdat(table2[i]); 
				}
			}
			else
			{
			  for(i=0;i<11;i++)
				{
					lcd_wcom(0x86+i);   
					lcd_wdat(table3[i]); 
				}				
			}	
		}
	}
}
void main(void)            //主函数,单片机开机后就是从这个函数开始运行
{

		lcd_init(); 	//液晶初始化
 		time_init();
		while(1)
		{
			api();	
		}
}

其中timing_display实现了定时的显示;data_display实现了日期的显示;time_display实现了时间的显示;beep_on实现了准点蜂鸣器响(该缺点暂时使用了delay_ms(50)此类操作,从而占用了单片机前台刷新LCD,但是由于定时、日期等后台计数不会影响;可以考虑加入定时器1来进行延时的计算,保证LCD的刷新)

4、其他重要功能函数

cpp 复制代码
void time_display()
{
	lcd_wcom(0x80);   
	lcd_wdat(table[shi/10]); 	
	lcd_wcom(0x81);  
	lcd_wdat(table[shi%10]); 
	lcd_wcom(0x82);  
	lcd_wdat(table[10]); 

	lcd_wcom(0x83);  
	lcd_wdat(table[fen/10]); 
	lcd_wcom(0x84);  
	lcd_wdat(table[fen%10]); 
	lcd_wcom(0x85);  
	lcd_wdat(table[10]); 

	lcd_wcom(0x86);  
	lcd_wdat(table[miao/10]);
	lcd_wcom(0x87);   
	lcd_wdat(table[miao%10]); 
	lcd_wcom(0x88);  
}

void timing_display()
{
	if(TIME_CLK==1000)
	TIME_CLK=0;
	lcd_wcom(0x80);   
	lcd_wdat(table[TIME_CLK/1000]); 	
	lcd_wcom(0x81);  
	lcd_wdat(table[TIME_CLK/100%10]); 
	lcd_wcom(0x82);  
	lcd_wdat(table[TIME_CLK%100/10]); 
	lcd_wcom(0x83);  
	lcd_wdat(table[11]); 
 	lcd_wcom(0x84);  
	lcd_wdat(table[TIME_CLK%10]); 
}

void date_display()
{
	int a[12]={31,28,31,30,31,30,31,31,30,31,30,31};
	int b[12]={31,29,31,30,31,30,31,31,30,31,30,31};
	if(nian%100==0)
	{	if(nian%4==0)
			if(ri>b[yue])
				{
					ri=1;
					yue+=1;
				}
	}
	else if(nian%4==0)
	{
		if(ri>b[yue])
			{
				ri=1;
				yue+=1;
			}
	}
	else 
	{
		if(ri>a[yue])
			{
				ri=1;
				yue+=1;
			}	
	}	
	if(yue==13)
	{
		yue=1;
		nian+=1;
	}
	lcd_wcom(0x80);   
	lcd_wdat(table4[nian/1000]); 	
	lcd_wcom(0x81);  
	lcd_wdat(table4[nian/100%10]); 
	lcd_wcom(0x82);  
	lcd_wdat(table4[nian%100/10]); 
	lcd_wcom(0x83);  
	lcd_wdat(table4[nian%10]); 
	lcd_wcom(0x84);  
	lcd_wdat(table4[10]); 

	lcd_wcom(0x85);  
	lcd_wdat(table4[yue/10]); 
	lcd_wcom(0x86);  
	lcd_wdat(table4[yue%10]); 
	lcd_wcom(0x87);  
	lcd_wdat(table4[10]); 

	lcd_wcom(0x88);  
	lcd_wdat(table4[ri/10]);
	lcd_wcom(0x89);   
	lcd_wdat(table4[ri%10]); 
	lcd_wcom(0x8A);
	 
}
void beep_on()
{
	BEEP_Control=1;
	BEEP=0;
	delay_ms(50);
	BEEP=1;
	delay_ms(50);
	BEEP=0;
	delay_ms(50);
	BEEP=1;
	delay_ms(50);
	BEEP=0;
	delay_ms(50);
	BEEP=1;
	delay_ms(50);
	BEEP=0;
	delay_ms(50);
	BEEP=1;
	delay_ms(50);
	BEEP=0;
	delay_ms(50);
	BEEP=1;
	delay_ms(50);
	BEEP=0;
	delay_ms(1000);
	BEEP=1;
	delay_ms(1000);

}

后续还有其他两个方法,在下一个博客进行介绍。

相关推荐
清风66666616 小时前
基于单片机与DAC0832的双路波形信号发生系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
azwsm17 小时前
电路元器件和GPIO控制器
单片机·嵌入式硬件
kebidaixu21 小时前
FreeRTOS 移植到 STM32F407VETX 记录(一)
stm32·单片机·嵌入式硬件
CSDN官方博客21 小时前
「谁说嵌入式只是调包和焊板子?」—— 2026嵌入式全栈技术征锋令
嵌入式硬件·物联网·embedding
点灯小铭1 天前
基于单片机的数码管定时插座设计与定时开关功能实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
云栖梦泽1 天前
玩转RK3506SDK
linux·嵌入式硬件
数智工坊1 天前
机器人四大主控板系统分层选型指南:树莓派、ESP32、STM32与Arduino的能力边界与实战定位
stm32·嵌入式硬件·机器人
石家庄光大远通电气1 天前
学生公寓智能限电系统的组成和功能介绍
硬件工程
进击的小头1 天前
第8篇:IGBT 从零到精通:核心原理、关键参数、选型指南与工业级应用要点
经验分享·嵌入式硬件·学习
点灯小铭1 天前
基于单片机的多模式智能洗衣机设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业