单片机DS1302时钟&可调时钟案例

本案例是依照b站  江协科技  案例改编而成,大家也可以去访问一下原帖,这里只做简单的介绍

[10-2] DS1302时钟&可调时钟_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1Mb411e7re?p=24&vd_source=4ab446c3ef7b54124da55868706ad2bc下面我简单介绍一下

大家可以去看看芯片的手册,这里不作过多赘述。所有的资料放在网盘链接中,需要的自取

链接: https://pan.baidu.com/s/1QTrG63XKrK8HgF7yl2oc3A?pwd=qad9 提取码: qad9

本案例,是基于普中的51_A2开发板来实现的,需要用到LCD1602显示屏,开发板(DS1302芯片已经在开发板中)

按键调节时钟

下面看看代码

主函数部分:

#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Delay.h"
#include "Key.h"
#include "Timer0.h"

unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;

void TimeShow(void)
{
		DS1302_ReadTime();

		LCD_ShowNum(1,1,DS1302_Time[0],2);//Second
		LCD_ShowNum(1,4,DS1302_Time[1],2);
		LCD_ShowNum(1,7,DS1302_Time[2],2);
		LCD_ShowNum(2,1,DS1302_Time[3],2);
		LCD_ShowNum(2,4,DS1302_Time[4],2);
		LCD_ShowNum(2,7,DS1302_Time[5],2);
		LCD_ShowNum(2,10,DS1302_Time[6],2);
}
void TimeSet(void)
{
	if(KeyNum==2)
	{
		TimeSetSelect++;
		if(TimeSetSelect>6){TimeSetSelect=0;}
		//TimeSetSelect%=6;
	}
	if(KeyNum==3)
	{
		DS1302_Time[TimeSetSelect]++;
		/**********年*************/
		if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//年
		/**********月*************/
		if(DS1302_Time[1]>12){DS1302_Time[1]=1;}//月
		/**********日*************/
		if(DS1302_Time[1]==1 || DS1302_Time[1]==3	||
			DS1302_Time[1]==5 || DS1302_Time[1]==7 ||
			DS1302_Time[1]==8 || DS1302_Time[1]==10 ||
			DS1302_Time[1]==12 )
		{
			if(DS1302_Time[2]>31){DS1302_Time[2]=1;}//大月
		}
		else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || 
				DS1302_Time[1]==9 || DS1302_Time[1]==11)
		{
				if(DS1302_Time[2]>30){DS1302_Time[2]=1;}//小月
		}
		else if(DS1302_Time[1]>2)
			{
				if(DS1302_Time[0]%4==0)
				{
					if(DS1302_Time[2]>29){DS1302_Time[2]=1;}//闰月
				}
				else
				{
					if(DS1302_Time[2]>28){DS1302_Time[2]=1;}//平月
				}
			}

		if(DS1302_Time[3]>23){DS1302_Time[3]=0;}//时
		if(DS1302_Time[4]>59){DS1302_Time[4]=0;}//分
		if(DS1302_Time[5]>59){DS1302_Time[5]=0;}//秒
		if(DS1302_Time[6]>7){DS1302_Time[6]=1;}//星期
		//if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//
	}
	if(KeyNum==4)
	{
		DS1302_Time[TimeSetSelect]--;
		/**********年*************/
		if(DS1302_Time[0]<0){DS1302_Time[0]=99;}//年
		/**********月*************/
		if(DS1302_Time[1]<1){DS1302_Time[1]=12;}//月
		/**********日*************/
		if(DS1302_Time[1]==1 || DS1302_Time[1]==3	||
			DS1302_Time[1]==5 || DS1302_Time[1]==7 ||
			DS1302_Time[1]==8 || DS1302_Time[1]==10 ||
			DS1302_Time[1]==12 )
		{
			if(DS1302_Time[2]<1){DS1302_Time[2]=31;}//大月
		}
		else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || 
				DS1302_Time[1]==9 || DS1302_Time[1]==11)
		{
				if(DS1302_Time[2]<1){DS1302_Time[2]=30;}//小月
		}
		else if(DS1302_Time[1]>2)
			{
				if(DS1302_Time[0]%4==0)
				{
					if(DS1302_Time[2]<1){DS1302_Time[2]=29;}//闰月
				}
				else
				{
					if(DS1302_Time[2]<1){DS1302_Time[2]=28;}//平月
				}
			}

		if(DS1302_Time[3]<0){DS1302_Time[3]=23;}//时
		if(DS1302_Time[4]<0){DS1302_Time[4]=59;}//分
		if(DS1302_Time[5]<0){DS1302_Time[5]=59;}//秒
		if(DS1302_Time[6]<1){DS1302_Time[6]=7;}//星期
		//if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//
	}
	if(TimeSetSelect==0 && TimeSetFlashFlag==1){LCD_ShowString(1,1,"  ");}
	else {LCD_ShowNum(1,1,DS1302_Time[0],2);}//显示年}
	if(TimeSetSelect==1 && TimeSetFlashFlag==1){LCD_ShowString(1,4,"  ");}
	else {LCD_ShowNum(1,4,DS1302_Time[1],2);}//显示月}
	if(TimeSetSelect==2 && TimeSetFlashFlag==1){LCD_ShowString(1,7,"  ");}
	else {LCD_ShowNum(1,7,DS1302_Time[2],2);}//显示日}
	if(TimeSetSelect==3 && TimeSetFlashFlag==1){LCD_ShowString(2,1,"  ");}
	else {LCD_ShowNum(2,1,DS1302_Time[3],2);}//显示时}
	if(TimeSetSelect==4 && TimeSetFlashFlag==1){LCD_ShowString(2,4,"  ");}
	else {LCD_ShowNum(2,4,DS1302_Time[4],2);}//显示分}
	if(TimeSetSelect==5 && TimeSetFlashFlag==1){LCD_ShowString(2,7,"  ");}
	else {LCD_ShowNum(2,7,DS1302_Time[5],2);}//显示秒}
	if(TimeSetSelect==6 && TimeSetFlashFlag==1){LCD_ShowString(2,10,"  ");}
	else {LCD_ShowNum(2,10,DS1302_Time[6],2);}//显示星期}

}

unsigned char Second,Minute;
void main()
{
	LCD_Init();
	DS1302_Init();
	Timer0Init();
	DS1302_SetTime();
	LCD_ShowString(1,1,"  -  -");
	LCD_ShowString(2,1,"  :  :  >");
	
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
			if(MODE==0){MODE=1;}
			else if(MODE==1){MODE=0;DS1302_SetTime();}
		}
		switch(MODE)
		{
			case 0:TimeShow();break;
			case 1:TimeSet();break;
		}
		



	}

}

void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;
	if (T0Count>=500)
	{
		T0Count=0;
		TimeSetFlashFlag=!TimeSetFlashFlag;

	}

}

主函数包含了时钟的调节逻辑,可以实现显示:年、月、日、时、分、秒、星期。

其他的,我们都采用模块化来实现:

我们先来看看,DS1302的模块:

#include <REGX52.H>
/**********端口的定义*************/
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;

#define DS1302_SECOND	0X80
#define DS1302_MINUTE	0X82
#define DS1302_HOUR		0X84
#define DS1302_DATE		0X86
#define DS1302_MONTH		0X88
#define DS1302_DAY		0X8A
#define DS1302_YEAR		0X8C
#define DS1302_WP			0X8E


char DS1302_Time[]={24,7,25,22,10,0,4};
/**********DS1302的初始化*************/
void DS1302_Init(void)
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}
/*********DS1302写操作**************/
void DS1302_WriteByte(unsigned char Command,Data)
{
	unsigned char i;
	DS1302_CE=1;
	
	for(i=0;i<8;i++)
	{
	DS1302_IO=Command&(0X01<<i);
	DS1302_SCLK=1;
	DS1302_SCLK=0;
	}
	for(i=0;i<8;i++)
	{
	DS1302_IO=Data&(0X01<<i);
	DS1302_SCLK=1;
	DS1302_SCLK=0;
	}
	DS1302_CE=0;
}
/**********DS1302读操作*************/
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Data=0X00;
	Command|=0X01;
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
	DS1302_IO=Command&(0X01<<i);
	DS1302_SCLK=0;
	DS1302_SCLK=1;
	}
	for(i=0;i<8;i++)
	{
	DS1302_SCLK=1;
	DS1302_SCLK=0;
	if(DS1302_IO){Data=Data|(0X01<<i);}
	}
	DS1302_CE=0;
	DS1302_IO=0;
	return Data;
}
/*********DS1302更改时间**************/
void DS1302_SetTime(void)
{
	DS1302_WriteByte(DS1302_WP,0X00);
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);
	DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
	DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
	DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10);
	DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10);
	DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10);
	DS1302_WriteByte(DS1302_DAY,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
	DS1302_WriteByte(DS1302_WP,0X80);
}
/**********DS1302显示读取时间*************/
void DS1302_ReadTime(void)
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_MINUTE);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_SECOND);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_DAY);
	DS1302_Time[6]=Temp/16*10+Temp%16;

}

模块化之后,记得在主函数里面去调用。最后可以实现,所有的模块,都在网盘上,需要的可以自取。

我们使用开发板中的独立按键来实现时钟的调节功能。当目标被调节时呈现闪烁状态。

K1:切换成调节模式;K2:切换调节的目标;K3:按键+;K4:按键-;

我们来看看,芯片硬件部分原理图:

最后看看实物演示:

最后我们就实现了,但注意的是,开发板本身不带备用电源,断电后,时间将被复位。本案例也仅供学习使用,详细原理可以移步b站  江协科技 

[10-2] DS1302时钟&可调时钟_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1Mb411e7re?p=24&vd_source=4ab446c3ef7b54124da55868706ad2bc到这里就完成啦,也有不足的地方,希望指正!

最后,感谢你能看到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值