DS1302可调时钟

最重要的是逻辑问题和调试的过程,需要耐心!

1、首先是定义两个参数用于按键一来切换编辑或者显示模式

KeyNum用于接收按键键码

Mode用来判断当前模式

unsigned char KeyNum,Mode;

在主函数中写出按下按键1切换模式

void main(void)
{
	LCD_Init();
	DS1302_Init();
	
	DS1302_TimeSet();
	
	LCD_ShowString(1,5,"-  -");
	LCD_ShowString(2,3,":  :");
	while(1)
	{
		KeyNum = Key();
		if(KeyNum == 1)
		{
			if(Mode ==1) {Mode = 0;}
			else if(Mode == 0) {Mode = 1;}
		}
	}
}

2、再编写出显示时间函数和编辑时间函数

显示函数,比较简单,只是把定义好的时间显示出来

void TimeShow(void)
{
	DS1302_TimeRead();
	LCD_ShowNum(1,1,20,2);
	LCD_ShowNum(1,3,Time_R[0],2);//Äê
	LCD_ShowNum(1,6,Time_R[1],2);//ÔÂ
	LCD_ShowNum(1,9,Time_R[2],2);//ÈÕ
	LCD_ShowNum(2,1,Time_R[3],2);//ʱ
	LCD_ShowNum(2,4,Time_R[4],2);//·Ö
	LCD_ShowNum(2,7,Time_R[5],2);//Ãë
}

编辑函数

有三个要素

第一是选择编辑的量,第二是加,第三是减。

首先是选择编辑的量,先定义一个选择定义Time_R的索引值的变量

unsigned char TimeSetSelect;

 在函数中如是编写,因为只有6个选项,且数组索引值是0~5,所以要做溢出判断。

最后一行语句是用于调试的,可以观察当前的索引值指向哪一位。

void TimeSet(void)
{
    if(KeyNum == 2)
    	{
	    	TimeSetSelect++;
	    	if(TimeSetSelect == 6) TimeSetSelect = 0;
	    }
    LCD_ShowNum(2,15,TimeSetSelect,2);
}

接下来就是写加减的语句了,不难懂

else if(KeyNum == 3)
	{
		Time_R[TimeSetSelect]++;
	}
else if(KeyNum == 4)
	{
		Time_R[TimeSetSelect]--;
    }

还要记得更新显示,不然结果是不会显示出来的

LCD_ShowNum(1,1,20,2);
	LCD_ShowNum(1,3,Time_R[0],2);//Äê
	LCD_ShowNum(1,6,Time_R[1],2);//ÔÂ
	LCD_ShowNum(1,9,Time_R[2],2);//ÈÕ
	LCD_ShowNum(2,1,Time_R[3],2);//ʱ
	LCD_ShowNum(2,4,Time_R[4],2);//·Ö
	LCD_ShowNum(2,7,Time_R[5],2);//Ãë

但是这个加减法太简单了,以至于会出现数值越界,即13月26时66分89秒等等情况 

所以要对加减法做出相对应的越界判断(不仅包括越界,还包括判断闰年,大月小月等情况)

加法的越界判断

else if(KeyNum == 3)
	{
		Time_R[TimeSetSelect]++;
		

		if(Time_R[0] > 99) Time_R[0] = 0;//Year
		if(Time_R[1] > 12) Time_R[1] = 1;//Month
		
		if(Month(Time_R[1]) == 1){if(Time_R[2] > 31) Time_R[2] = 1;}
		else if(Month(Time_R[1]) == 2)
			{
				if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0  || Time_R[0]%400==0)
				{
					if(Time_R[2] > 29) Time_R[2] = 1;
				}
				else
				{
					if(Time_R[2] > 28) Time_R[2] = 1;
				}
			}
		else if(Month(Time_R[1]) == 3){if(Time_R[2] > 30) Time_R[2] = 1;}//Èç¹ûÊÇСÔÂ
		//Date
		
		if(Time_R[3] > 23) Time_R[3] = 0;//Hour
		if(Time_R[4] > 59) Time_R[4] = 0;//Minute
		if(Time_R[5] > 59) Time_R[5] = 0;//Second
	}

减法的越界判断

else if(KeyNum == 4)
	{
		Time_R[TimeSetSelect]--;

		if(Time_R[0] < 0) Time_R[0] = 99;//Year
		if(Time_R[1] < 1) Time_R[1] = 12;//Month
		
		if(Month(Time_R[1]) == 1){if(Time_R[2] < 1) Time_R[2] = 31;}
		else if(Month(Time_R[1]) == 2)
		{
			if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0  || Time_R[0]%400==0)
				{
					if(Time_R[2] < 1) Time_R[2] = 29;
				}
				else
				{
					if(Time_R[2] < 1) Time_R[2] = 28;
				}ê
		}
		else if(Month(Time_R[1]) == 3){if(Time_R[2] < 1) Time_R[2] = 30;}//Date
		
		if(Time_R[3] < 0) Time_R[3] = 23;//Hour
		if(Time_R[4] < 0) Time_R[4] = 59;//Minute
		if(Time_R[5] < 0) Time_R[5] = 59;//Second
	}

 可得最终TimeSet()

void TimeSet(void)
{
	if(KeyNum == 2)
	{
		TimeSetSelect++;
		if(TimeSetSelect == 6) TimeSetSelect = 0;
	}
	else if(KeyNum == 3)
	{
		Time_R[TimeSetSelect]++;
		
		if(Time_R[0] > 99) Time_R[0] = 0;//Year
		if(Time_R[1] > 12) Time_R[1] = 1;//Month
		
		if(Month(Time_R[1]) == 1){if(Time_R[2] > 31) Time_R[2] = 1;
		else if(Month(Time_R[1]) == 2)
			{
				if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0  || Time_R[0]%400==0)
				{
					if(Time_R[2] > 29) Time_R[2] = 1;
				}
				else
				{
					if(Time_R[2] > 28) Time_R[2] = 1;
				}
			}
		else if(Month(Time_R[1]) == 3){if(Time_R[2] > 30) Time_R[2] = 1;}
		//Date
		
		if(Time_R[3] > 23) Time_R[3] = 0;//Hour
		if(Time_R[4] > 59) Time_R[4] = 0;//Minute
		if(Time_R[5] > 59) Time_R[5] = 0;//Second
	}
	else if(KeyNum == 4)
	{
		Time_R[TimeSetSelect]--;
		if(Time_R[0] < 0) Time_R[0] = 99;//Year
		if(Time_R[1] < 1) Time_R[1] = 12;//Month
		
		if(Month(Time_R[1]) == 1){if(Time_R[2] < 1) Time_R[2] = 31;}
		else if(Month(Time_R[1]) == 2)
		{
			if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0  || Time_R[0]%400==0)
				{
					if(Time_R[2] < 1) Time_R[2] = 29;
				}
				else
				{
					if(Time_R[2] < 1) Time_R[2] = 28;
				}
		}
		else if(Month(Time_R[1]) == 3){if(Time_R[2] < 1) Time_R[2] = 30;}//Date
		
		if(Time_R[3] < 0) Time_R[3] = 23;//Hour
		if(Time_R[4] < 0) Time_R[4] = 59;//Minute
		if(Time_R[5] < 0) Time_R[5] = 59;//Second
	}
	LCD_ShowNum(2,15,TimeSetSelect,2);
	
	LCD_ShowNum(1,1,20,2);
	LCD_ShowNum(1,3,Time_R[0],2);//Äê
	LCD_ShowNum(1,6,Time_R[1],2);//ÔÂ
	LCD_ShowNum(1,9,Time_R[2],2);//ÈÕ
	LCD_ShowNum(2,1,Time_R[3],2);//ʱ
	LCD_ShowNum(2,4,Time_R[4],2);//·Ö
	LCD_ShowNum(2,7,Time_R[5],2);//Ãë
}

在写好两个函数后,需要在main函数中调用这两个函数

在Mode == 0时为时间显示模式,在Mode==1时为时间编辑模式

    if(Mode == 0) TimeShow();
	else if(Mode == 1) TimeSet();

 但是我们可以看到即使我们已经设置好了新的时间,可显示还是按照之前的时间运行,所以我们需要重新调用DS1302来设置时间,只需在按下按键一转换为显示模式后再加一个DS1302_TimeSet()即可

 如图,其中还有些小细节

 3、接下来就是编写编辑时间元素时闪烁的代码了

需要用到Timer0.c

首先先初始化

Timer0_Init();

然后是引入先前编好的中断号函数

unsigned int T0Count = 0;
void Timer0_Rountine(void) interrupt 1
{
	T0Count++;
	TL0 = 0x66;		
	TH0 = 0xFC;
	if (T0Count >= 500)
	{
		T0Count = 0;
		
	}
}

思路:引入一个变量,让这个变量没0.5s从0~1之间变化一次,当变量为1时,选中的时间变为空,当变量为0时,选中的时间恢复原状,这样在0.5s变化一次的频率下,选中的时间就没0.5s闪烁一次。

这里引入SetFlash

unsigned char SetFlash

写入中断函数中

void Timer0_Rountine(void) interrupt 1
{
	T0Count++;
	TL0 = 0x66;		
	TH0 = 0xFC;
	if (T0Count >= 500)
	{
		T0Count = 0;
		SetFlash = ! SetFlash;
	}
}

(注意:!0 = 1,按逻辑取反;~0 = 0xff,按位取反)

在TimeSet中

    if(TimeSetSelect == 0 && SetFlash == 1) {LCD_ShowString(1,1,"    ");}
	else{LCD_ShowNum(1,1,20,2);LCD_ShowNum(1,3,Time_R[0],2);}//Year
	
	if(TimeSetSelect == 1 && SetFlash == 1) {LCD_ShowString(1,6,"  ");}
	else{LCD_ShowNum(1,6,Time_R[1],2);}//Month
	
	if(TimeSetSelect == 2 && SetFlash == 1) {LCD_ShowString(1,9,"  ");}
	else{LCD_ShowNum(1,9,Time_R[2],2);}
	
	if(TimeSetSelect == 3 && SetFlash == 1) {LCD_ShowString(2,1,"  ");}
	else{LCD_ShowNum(2,1,Time_R[3],2);}
	
	if(TimeSetSelect == 4 && SetFlash == 1) {LCD_ShowString(2,4,"  ");}
	else{LCD_ShowNum(2,4,Time_R[4],2);}
	
	if(TimeSetSelect == 5 && SetFlash == 1) {LCD_ShowString(2,7,"  ");}
	else{LCD_ShowNum(2,7,Time_R[5],2);}

 则可完成目标!

总体:

DS1302.c

#include <REGX52.H>

void DS1302_WriteByte(unsigned char Command,Data);

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


unsigned char Time_R[] = {23,9,8,6,20,10,5};

unsigned char Time_W[] = {
	DS1302_Year,DS1302_Month,DS1302_Date,
	DS1302_Hour,DS1302_Minute,DS1302_Second,
	DS1302_Day
};


void DS1302_Init(void)//³õʼ»¯DS1302
{
	DS1302_CE = 0;
	DS1302_SCLK = 0;
}


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;
}

unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Result = 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) {Result |= (0x01 << i);}
	}
	
	DS1302_CE = 0;
	DS1302_IO = 0;
	return Result;
}

void DS1302_TimeSet(void)
{
	unsigned char i,Time;
	DS1302_WriteByte(DS1302_WP, 0x00);//¹Ø±Õд±£»¤
	for (i = 0; i < 7; i++)
	{
		Time = Time_R[i];
		DS1302_WriteByte(Time_W[i], Time_R[i] / 10 * 16 + Time_R[i] % 10);

	}
	DS1302_WriteByte(DS1302_WP, 0x80);
}


void DS1302_TimeRead(void)
{
	unsigned char i,Temp,Time_Re;
	for (i = 0; i < 7; i++)
	{
		Temp = DS1302_ReadByte(Time_W[i]);
		Time_R[i] = Temp / 16 * 10 + Temp % 16; 

	}
}

 

 DS1302.h

#ifndef ___DS1302_H__
#define __DS1302_H__

extern unsigned char Time_R[];

void DS1302_Init(void);
void DS1302_WriteByte(unsigned char Command,Data);
unsigned char DS1302_ReadByte(unsigned char Command);
void DS1302_TimeSet(void);
void DS1302_TimeRead(void);

#endif

Month.c

unsigned char Month(unsigned char num)
{
	unsigned char result,i;
	unsigned char Month_B[]={1,3,5,7,8,10,12};
	unsigned char Month_S[]={4,6,9,11};
	for(i = 0; i < 7; i++)
	{
		if(num == Month_B[i]){return 1;}
	}
	if(num == 2){return 2;}
	for(i = 0; i < 4; i++)
	{
		if(num == Month_S[i]){return 3;}
	}
	
}

main.c

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

unsigned char KeyNum,Mode,TimeSetSelect,SetFlash;
//KeyNum¼üÂ룬Mode¿ØÖÆTimeSetºÍTimeShow,TimeSetSelectÊÇTimeSetÑ¡ÔñµÄλÖÃ

unsigned int T0Count = 0;
void Timer0_Rountine(void);
	
void TimeShow(void)
{
	DS1302_TimeRead();
	LCD_ShowNum(1,1,20,2);
	LCD_ShowNum(1,3,Time_R[0],2);//Äê
	LCD_ShowNum(1,6,Time_R[1],2);//ÔÂ
	LCD_ShowNum(1,9,Time_R[2],2);//ÈÕ
	LCD_ShowNum(2,1,Time_R[3],2);//ʱ
	LCD_ShowNum(2,4,Time_R[4],2);//·Ö
	LCD_ShowNum(2,7,Time_R[5],2);//Ãë
}

void TimeSet(void)
{
	if(KeyNum == 2)
	{
		TimeSetSelect++;
		if(TimeSetSelect == 6) TimeSetSelect = 0;
	}//TimeSetSelect¹²ÓÐ6¸öÊý£¬0~5¿ÉÒÔ±íʾTime_R[]ÖеÄÿ¸öÔªËصÄË÷ÒýÖµ
	else if(KeyNum == 3)
	{
		Time_R[TimeSetSelect]++;
		
		//Ô½½çÅжÏ
		if(Time_R[0] > 99) Time_R[0] = 0;//Year
		if(Time_R[1] > 12) Time_R[1] = 1;//Month
		
		if(Month(Time_R[1]) == 1){if(Time_R[2] > 31) Time_R[2] = 1;}//Èç¹ûÊÇ´óÔÂ
		else if(Month(Time_R[1]) == 2)
			{
				if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0  || Time_R[0]%400==0)
				{
					if(Time_R[2] > 29) Time_R[2] = 1;
				}//ÈòÄê
				else
				{
					if(Time_R[2] > 28) Time_R[2] = 1;
				}//·ÇÈòÄê
			}//Èç¹ûÊÇ2ÔÂ
		else if(Month(Time_R[1]) == 3){if(Time_R[2] > 30) Time_R[2] = 1;}//Èç¹ûÊÇСÔÂ
		//Date
		
		if(Time_R[3] > 23) Time_R[3] = 0;//Hour
		if(Time_R[4] > 59) Time_R[4] = 0;//Minute
		if(Time_R[5] > 59) Time_R[5] = 0;//Second
	}
	else if(KeyNum == 4)
	{
		Time_R[TimeSetSelect]--;
		//Ô½½çÅжÏ
		//×¢ÒâÕâÀïÈç¹ûʹÓõÄÊÇÎÞ·ûºÅµÄÀàÐÍ£¬Time_R[] = 0 ÔÙ--ºó»á±ä³É255
		//ҪʹÓÃ<ÅжϵĻ°£¬Òª°ÑÎÞ·ûºÅ¸Ä³ÉÓзûºÅ£¬¼´È¥µôunsigned
		if(Time_R[0] < 0) Time_R[0] = 99;//Year
		if(Time_R[1] < 1) Time_R[1] = 12;//Month
		
		if(Month(Time_R[1]) == 1){if(Time_R[2] < 1) Time_R[2] = 31;}
		else if(Month(Time_R[1]) == 2)
		{
			if(Time_R[0] % 4==0 && Time_R[0] % 100 !=0  || Time_R[0]%400==0)
				{
					if(Time_R[2] < 1) Time_R[2] = 29;
				}//ÈòÄê
				else
				{
					if(Time_R[2] < 1) Time_R[2] = 28;
				}//·ÇÈòÄê
		}
		else if(Month(Time_R[1]) == 3){if(Time_R[2] < 1) Time_R[2] = 30;}//Date
		
		if(Time_R[3] < 0) Time_R[3] = 23;//Hour
		if(Time_R[4] < 0) Time_R[4] = 59;//Minute
		if(Time_R[5] < 0) Time_R[5] = 59;//Second
	}
	//ÓÃÓÚµ÷ÊÔTimeSetSelectµÄÊýÖµ
	LCD_ShowNum(2,15,TimeSetSelect,2);
	
	if(TimeSetSelect == 0 && SetFlash == 1) {LCD_ShowString(1,1,"    ");}
	else{LCD_ShowNum(1,1,20,2);LCD_ShowNum(1,3,Time_R[0],2);}//Year
	
	if(TimeSetSelect == 1 && SetFlash == 1) {LCD_ShowString(1,6,"  ");}
	else{LCD_ShowNum(1,6,Time_R[1],2);}//Month
	
	if(TimeSetSelect == 2 && SetFlash == 1) {LCD_ShowString(1,9,"  ");}
	else{LCD_ShowNum(1,9,Time_R[2],2);}
	
	if(TimeSetSelect == 3 && SetFlash == 1) {LCD_ShowString(2,1,"  ");}
	else{LCD_ShowNum(2,1,Time_R[3],2);}
	
	if(TimeSetSelect == 4 && SetFlash == 1) {LCD_ShowString(2,4,"  ");}
	else{LCD_ShowNum(2,4,Time_R[4],2);}
	
	if(TimeSetSelect == 5 && SetFlash == 1) {LCD_ShowString(2,7,"  ");}
	else{LCD_ShowNum(2,7,Time_R[5],2);}
	
}

void main(void)
{
	LCD_Init();
	DS1302_Init();
	
	DS1302_TimeSet();
	Timer0_Init();
	
	LCD_ShowString(1,5,"-  -");
	LCD_ShowString(2,3,":  :");
	while(1)
	{
		KeyNum = Key();
		if(KeyNum == 1)
		{
			if(Mode ==1) 
			{
				Mode = 0;
				LCD_ShowString(2,15,"  ");//°ÑÊý×éË÷ÒýÒþ²Ø
				DS1302_TimeSet();//ÉèÖñ༭ºÃµÄʱ¼ä
			}
			else if(Mode == 0) {Mode = 1;TimeSetSelect = 0;}
		}//°´Ï°´¼üÒ»Çл»Ä£Ê½
		
		if(Mode == 0) TimeShow();
		else if(Mode == 1) TimeSet();
		//¸ù¾ÝModeµÄÖµÅжÏģʽ

	}
}

void Timer0_Rountine(void) interrupt 1
{
	T0Count++;
	TL0 = 0x66;		
	TH0 = 0xFC;
	if (T0Count >= 500)
	{
		T0Count = 0;
		SetFlash = ! SetFlash;
		//Âß¼­·Ç,0 = £¡1
		//~°´Î»È¡·´£¬~0 = 0xff;
	}
}

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值