用红外遥控器来调DS1302时钟的时间,可以实现,按一下调时间的键,来调秒,按加号键秒+1,按减号键秒-1,再次按调时间的键调分钟,在按调小时,同理,年月日,时分秒都能调节,而且逻辑正确,不管是闰年还是闰月等都会加到相应的天数就恢复为1,例如某个2月是29天,那末当调节天的时候,网上+,加到29,再加会变成1,同理,其他月份都是这样的,当调整完时间后,再次按下调整时间按钮,时间开始从你调节的时间开始运行。
代码在慧静51单片机上测试通过,其他单片机稍微调整引脚即可。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v9W2p3Ny-1607993246787)(IMG_20201215_084356#pic_center)]
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCLK=P2^1; //时钟
sbit IO=P2^0; //数据
sbit CE=P2^4; //DS1302复位(片选)
sbit rs=P1^0;
sbit rw=P1^1;
sbit en=P2^5;
sbit BF=P0^7;
sbit FM=P2^3;
sbit duan=P2^6;
uchar yue,chao;
uchar flag_hong;
uchar irtime,extern1_num,bit_num,flag_irtime_ok;
uchar data_irtime[33],data_ircode[4],flag;
char time[7]={0,12,21,13,4,7,20};//秒分时日月周年13-08-15 23:59:50
uchar flag2;
uchar w;
/***********以下为LCD1602部分
***********************************************/
//判忙函数
void panmang()
{
P0=0xff; //注意:先拉高才能正确的读取
do
{
rs=0;
rw=1;
en=0;
en=1;
}while(BF==1);
en=0;
}
//写数据的函数
void write_date(uchar date)
{
panmang();
rs=1;
rw=0;
P0=date;
en=0;
en=1;
en=0;
}
//写指令的函数
void write_com(uchar com)
{
panmang();
rs=0;
rw=0;
P0=com;
en=0;
en=1;
en=0;
}
//初始化的函数
void init_LCD1602()
{
duan=1;
P0=0;
duan=0;
en=0;
write_com(0x38); //162显示
write_com(0x0c); //开显示 不显示光标 光标不闪烁
write_com(0x06); //光标地址都自加1
write_com(0x01); //注意:清屏指令
}
/************以下为DS1302的部分
**********************************************************/
//延时函数
void delay(uint n)
{
while (n–);
}
//三条线初始化的函数
void xian_init()
{
CE=0;
SCLK=0;
IO=0;
}
//写一个字节的函数
void writezijie(uchar date)
{
uchar i;
SCLK=0;
for(i=0;i<8;i++)
{
IO=date&0x01;
SCLK=1;
date>>=1;
SCLK=0;
}
}
//读一个字节的函数
uchar duzijie()
{
uchar i,date=0;
for(i=0;i<8;i++)
{
date>>=1;
if(IO==1)
date|=0x80;
SCLK=1;
SCLK=0;
}
return date;
}
//写数据的函数
void writeshuju(uchar addr,uchar shuju)
{
xian_init();
CE=1;
writezijie(addr);
writezijie(shuju);
IO=0;
CE=0;
}
//读数据的函数
uchar readshuju(uchar addr)
{
uchar temp;
xian_init();
CE=1;
writezijie(addr);
temp=duzijie();
IO=0;
CE=0;
return temp;
}
//清除写保护
void clear_wp()
{
xian_init();
CE=1;
writezijie(0x8e);
writezijie(0);
IO=0;
CE=0;
}
//设置写保护
void setup_wp()
{
xian_init();
CE=1;
writezijie(0x8e);
writezijie(1);
IO=0;
CE=0;
}
//将数据转换成BCD码的形式
void zhuanhuan_BCD(uchar shuzu)
{
uchar an,i;
for(i=0;i<7;i++)
{
an=shuzu[i]/10;
shuzu[i]=shuzu[i]%10;
shuzu[i]=shuzu[i]+an16;
}
}
//给寄存器初始化的数据
void chushihua()
{ uchar tmp,i;
tmp=0x80; //传写地址
for(i=0;i<7;i++) //7次写入
{
writeshuju(tmp,time[i]);
tmp+=2;
}
}
//从寄存器中读取数据的函数
void dujicunqi(uchar *timedata)
{
if(flag_hong==0)
{
chao=0x81;
yue=0;
for(yue;yue<7;yue++)
{
timedata[yue]=readshuju(chao);
chao+=2;
}
}
else if(flag_hong==1)
{
delay(1000);
}
}
//时间停止的函数
void stop()
{
flag_hong=1;
clear_wp();
writeshuju(0x80,time[0]|0x80);
setup_wp();
}
//时间重新启动
void start()
{
uchar an;
flag_hong=0;
clear_wp();
an=time[0]&0x7f;
writeshuju(0x80,an);
writeshuju(0x82,time[1]&0x7f);
writeshuju(0x84,time[2]&0x7f);
writeshuju(0x86,time[3]&0x7f);
writeshuju(0x88,time[4]&0x7f);
writeshuju(0x8c,time[6]&0x7f);
setup_wp();
}
/**************以下为红外遥控部分
********************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
void delaynms(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
void beep() //蜂鸣器响一声函数
{
unsigned char i;
for (i=0;i<100;i++)
{
delay1ms();
FM=!FM; //BEEP取反
}
FM=1; //关闭蜂鸣器
delaynms(250); //延时
}
//定时器初始化的函数
void initial_timer0()
{
TMOD=0x02;
TH0=0;
TL0=0;
EA=1;
ET0=1;
TR0=1;
}
//外部中段0初始化的函数
void initial_extern0()
{
IT0=1;
EA=1;
EX0=1;
}
//定时器t0中断函数
void timer0() interrupt 1
{
irtime++;
}
//外部中断0的函数 根据每位数据的时间并将其储存到数组里
void extern0() interrupt 0
{
extern1_num++;
if(extern1_num1)
{
irtime=0;
}
else
{
if(irtime>48)
{
bit_num=0;
flag=1;
}
if(flag1)
{
data_irtime[bit_num]=irtime;
irtime=0;
bit_num++;
if(bit_num==33)
{
flag_irtime_ok=1;
extern1_num=0;
flag=0;
}
}
}
}
//根据每位数据的时间来转换成0和1
void irdata_processing()
{
uchar value,k=1,i,j;
for(j=0;j<4;j++)
{
for(i=0;i<8;i++)
{
value=value>>1;
if(data_irtime[k]>6)
{
value=value|0x80;
}
k++;
}
data_ircode[j]=value;
}
}
//将数据显示到LCD1602上
void lcd1602_display()
{
write_com(0x80+10);
if(data_ircode[2]/16<10)
{
write_date(data_ircode[2]/16+0x30);
}
else
{
write_date(data_ircode[2]/16+0x37);
}
if(data_ircode[2]%16<10)
{
write_date(data_ircode[2]%16+0x30);
}
else
{
write_date(data_ircode[2]%16+0x37);
}
}
//调节时间的函数
void tiaotime()
{
if(data_ircode[2]==0x09)
{
++w;
stop();
}
if(w==1) //调秒
{
if(data_ircode[2]==0x15)
{
clear_wp();
time[0]=time[0]&0x7f;
if(time[0]%16==0x9)
{
time[0]=time[0]|0xf;
}
time[0]++;
setup_wp();
if(time[0]/16==0x6)
{
clear_wp();
time[0]=0;
setup_wp();
}
}
if(data_ircode[2]==0x07)
{
clear_wp();
time[0]=time[0]&0x7f;
time[0]--;
if(time[0]%16==0xf)
{
switch(time[0]/16)
{
case 0x0: time[0]=0x09; break; //09
case 0x1: time[0]=0x19; break; //19
case 0x2: time[0]=0x29; break; //29
case 0x3: time[0]=0x39; break; //39
case 0x4: time[0]=0x49; break; //39
}
}
setup_wp();
if(time[0]==-1)
{
clear_wp();
time[0]=0x59;
setup_wp();
}
}
}
if(w==2) //调分
{
if(data_ircode[2]==0x15)
{
clear_wp();
time[1]=time[1]&0x7f;
if(time[1]%16==0x9)
{
time[1]=time[1]|0xf;
}
time[1]++;
setup_wp();
if(time[1]/16==0x6)
{
clear_wp();
time[1]=0;
setup_wp();
}
}
if(data_ircode[2]==0x07)
{
clear_wp();
time[1]=time[1]&0x7f;
time[1]--;
if(time[1]%16==0xf)
{
switch(time[1]/16)
{
case 0x0: time[1]=0x09; break; //09
case 0x1: time[1]=0x19; break; //19
case 0x2: time[1]=0x29; break; //29
case 0x3: time[1]=0x39; break; //39
case 0x4: time[1]=0x49; break; //39
}
}
setup_wp();
if(time[1]==-1)
{
clear_wp();
time[1]=0x59;
setup_wp();
}
}
}
if(w==3) //调小时
{
if(data_ircode[2]==0x15)
{
clear_wp();
time[2]=time[2]&0x7f;
if(time[2]%16==0x9)
{
time[2]=time[2]|0xf;
}
time[2]++;
setup_wp();
if(time[2]==0x24)
{
clear_wp();
time[2]=0;
setup_wp();
}
}
if(data_ircode[2]==0x07)
{
clear_wp();
time[2]=time[2]&0x7f;
time[2]--;
if(time[2]%16==0xf)
{
switch(time[2]/16)
{
case 0x0: time[2]=0x09; break; //09
case 0x1: time[2]=0x19; break; //19
}
}
setup_wp();
if(time[2]==-1)
{
clear_wp();
time[2]=0x23;
setup_wp();
}
}
}
if(w==4) //调天数
{
if(data_ircode[2]==0x15)
{
clear_wp();
time[3]=time[3]&0x7f;
if(time[3]%16==0x9)
{
time[3]=time[3]|0xf;
}
time[3]++;
setup_wp();
if(time[3]==0x32)
{
clear_wp();
time[3]=1;
setup_wp();
}
}
if(data_ircode[2]==0x07)
{
clear_wp();
time[3]=time[3]&0x7f;
time[3]--;
if(time[3]%16==0xf)
{
switch(time[3]/16)
{
case 0x0: time[3]=0x09; break; //09
case 0x1: time[3]=0x19; break; //19
case 0x2: time[3]=0x29; break; //29
}
}
setup_wp();
if(time[3]==0)
{
clear_wp();
time[3]=0x31;
setup_wp();
}
}
}
if(w==5) //调月份
{
if(data_ircode[2]==0x15)
{
clear_wp();
time[4]=time[4]&0x7f;
if(time[4]%16==0x9)
{
time[4]=time[4]|0xf;
}
time[4]++;
setup_wp();
if(time[4]==0x13)
{
clear_wp();
time[4]=1;
setup_wp();
}
}
if(data_ircode[2]==0x07)
{
clear_wp();
time[4]=time[4]&0x7f;
time[4]--;
if(time[4]%16==0xf)
{
switch(time[4]/16)
{
case 0x0: time[4]=0x09; break; //09
}
}
setup_wp();
if(time[4]==0)
{
clear_wp();
time[4]=0x12;
setup_wp();
}
}
}
if(w==6) //调年份
{
if(data_ircode[2]==0x15)
{
clear_wp();
time[6]=time[6]&0x7f;
if(time[6]%16==0x9)
{
time[6]=time[6]|0xf;
}
time[6]++;
setup_wp();
if(time[6]==0x70)
{
clear_wp();
time[6]=0x20;
setup_wp();
}
}
if(data_ircode[2]==0x07)
{
clear_wp();
time[6]=time[6]&0x7f;
time[6]--;
if(time[6]%16==0xf)
{
switch(time[6]/16)
{
case 0x0: time[0]=0x09; break; //09
case 0x1: time[0]=0x19; break; //19
case 0x2: time[0]=0x29; break; //29
case 0x3: time[0]=0x39; break; //39
case 0x4: time[0]=0x49; break; //49
case 0x5: time[0]=0x59; break; //59
}
}
setup_wp();
if(time[6]/16==0x1)
{
clear_wp();
time[6]=0x20;
setup_wp();
}
}
}
if(w==7)
{
w=0;
start();
}
}
//主函数
void main()
{
init_LCD1602(); //LCD1602初始化
initial_timer0(); //定时器0初始化
initial_extern0(); //外部中断0初始化
zhuanhuan_BCD(time);//将数组里的数据转换成BDC码的形式
clear_wp(); //清除写保护
chushihua(); //给寄存器写入数据 //秒分时日月周年13-08-15 23:59:50
setup_wp(); //设置写保护
while(1)
{
if(flag_irtime_ok==1)
{
irdata_processing();
flag_irtime_ok=0;
beep();
flag2=1;
}
lcd1602_display();
if(flag2==0)
{
dujicunqi(time);
write_com(0x80+0);
write_date(time[6]/16+'0'); //年
write_date(time[6]%16+'0'); //年
write_date('-');
write_date(time[4]/16+'0'); //月
write_date(time[4]%16+'0'); //月
write_date('-');
write_date(time[3]/16+'0'); //日
write_date(time[3]%16+'0'); //日
write_com(0x80+0x40+0);
write_date(time[2]/16+'0'); //时
write_date(time[2]%16+'0'); //时
write_date(':');
write_date(time[1]/16+'0'); //分
write_date(time[1]%16+'0'); //分
write_date(':');
write_date(time[0]/16+'0'); //秒
write_date(time[0]%16+'0'); //秒
delay(1000);
}
else
{
tiaotime();
flag2=0;
}
}
}