本案例是依照b站 江协科技 案例改编而成,大家也可以去访问一下原帖,这里只做简单的介绍
大家可以去看看芯片的手册,这里不作过多赘述。所有的资料放在网盘链接中,需要的自取
链接: 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时钟&可调时钟_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Mb411e7re?p=24&vd_source=4ab446c3ef7b54124da55868706ad2bc到这里就完成啦,也有不足的地方,希望指正!
最后,感谢你能看到这里。