单片机电子时钟问题,求高手解答。
小弟手上有一个单片机ds1302+lcd1602的程序。运行后发现,只要关闭电源,再打开。时钟就会自己初始化。程序如下:#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
/*****************************
1602液晶显示位定义
*****************************/
#define lcd_data P0
sbit rs=P2^6;
sbit rw=P2^5;
sbit en=P2^7;
void write_1602_cmd(uint);
void write_1602_dat(uint);
void delay1ms(uint);
void lcd1602_init();
uchar nyx[16]=" 2000-00-00 000 ";
uchar sfm[13] =" 00:00:00 ";
/******************************
ds1302的位定义
******************************/
sbit rst=P3^5;
sbit sclk=P3^6;
sbit io=P3^4;
void write_ds1302_byte(uint);
void lcd_busy_wait();
void write_ds1302(uint,uint);
uint read_ds1302(uint);
void init_time();
void read_time();
void xieshijian2(uint add,uint shu);
void xieshijian1(uint add,uint shu);
void xiexingqi(uint add,uint shu);
void time_bcd(uint x);
uint time_wadd[]={0x8c,0x88,0x86,0x8a,0x84,0x82,0x80};
uint time_radd[]={0x8d,0x89,0x87,0x8b,0x85,0x83,0x81};
uint time_init[7]={12,5,13,7,21,8,0};
uint time_shuzhi[7]={0,0,0,0,0,0,0};
uchar xingqi[7][3]={{"MON"},{"TUS"},{"WEN"},{"THU"},{"FRI"},{"STA"},{"SUN"}};
//按键定义
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;
//标志位定义
void keyscan();
uint gn_flag;
//程序开始
void main()
{
uint num;
lcd1602_init();
init_time();
write_1602_cmd(0x80);
for(num=0;num<16;num++)
{
write_1602_dat(nyx[num]);
}
write_1602_cmd(0x80+0x40);
for(num=0;num<13;num++)
{
write_1602_dat(sfm[num]);
}
while(1)
{
keyscan();
if(gn_flag==0)
{
read_time();
xieshijian2(10,time_shuzhi[6]);
xieshijian2(7,time_shuzhi[5]);
xieshijian2(4,time_shuzhi[4]);
xiexingqi(12,time_shuzhi[3]);
xieshijian1(9,time_shuzhi[2]);
xieshijian1(6,time_shuzhi[1]);
xieshijian1(3,time_shuzhi[0]);
}
}
}
/************************
1602读写时序操作
************************/
void write_1602_cmd(uint cmd)
{
lcd_busy_wait();
en=0;
rs=0;
rw=0;
lcd_data=cmd;
_nop_();
en=1;
_nop_();
en=0;
}
void write_1602_dat(uint dat)
{
lcd_busy_wait();
en=0;
rs=1;
rw=0;
lcd_data=dat;
_nop_();
en=1;
_nop_();
en=0;
}
void lcd1602_init()
{
write_1602_cmd(0x38);
delay1ms(4);
write_1602_cmd(0x0c);
write_1602_cmd(0x06);
write_1602_cmd(0x01);
lcd_data=0xff;
delay1ms(4);
}
void lcd_busy_wait()
{
rs=0;
rw=1;
en=1;
lcd_data= 0xff;
while(lcd_data&0x80);
en=0;
}
void delay1ms(uint x)
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
/*****************************
ds1302的时序操作
*****************************/
void write_ds1302_byte(uint date)
{
uint i;
for(i=0;i<8;i++)
{
sclk=0;
io=date&0x01;
date>>=1;
sclk=1;
}
}
void write_ds1302(uint cmd,uint date)
{
rst=0;
_nop_();
sclk=0;
_nop_();
rst=1;
_nop_();
write_ds1302_byte(cmd);
write_ds1302_byte(date);
rst=0;
_nop_();
io=1;
sclk=1;
}
uint read_ds1302(uint add)
{
uint shu,i;
rst=0;
_nop_();
sclk=0;
_nop_();
rst=1;
_nop_();
write_ds1302_byte(add);
for(i=0;i<8;i++)
{
shu>>=1;
sclk=0;
if(io) shu|=0x80;
sclk=1;
}
rst=0;
_nop_();
io=1;
sclk=1;
return shu;
}
void init_time()
{
uint i,a,b;
uchar second=read_ds1302(0x81);
if(second&0x80)
{
for(i=0;i<7;i++)
{
a=time_init[i]/10;
b=time_init[i]%10;
time_init[i]=a*16+b;
}
write_ds1302(0x8e,0x00);
for(i=0;i<7;i++)
{
write_ds1302(time_wadd[i],time_init[i]);
}
write_ds1302(0x8e,0x80);
}
}
void read_time()
{
uint i;
for(i=0;i<7;i++)
{
time_shuzhi[i]=read_ds1302(time_radd[i]);
}
}
void xieshijian2(uint add,uint shu)
{
uint a,b;
a=shu/16;
b=shu%16;
write_1602_cmd(0x80+0x40+add);
write_1602_dat(0x30+a);
write_1602_dat(0x30+b);
}
void xieshijian1(uint add,uint shu)
{
uint a,b;
a=shu/16;
b=shu%16;
write_1602_cmd(0x80+add);
write_1602_dat(0x30+a);
write_1602_dat(0x30+b);
}
void xiexingqi(uint add,uint shu)
{
uint i;
write_1602_cmd(0x80+add);
for(i=0;i<3;i++)
{
write_1602_dat(xingqi[shu-1][i]);
}
}
void time_bcd(uint x)
{
uint a,b;
a=time_shuzhi[x]/16;
b=time_shuzhi[x]%16;
if(b==0x0a)
{
a++;
b=0;
}
time_shuzhi[x]=a*16+b;
}
/********************************
按键设置时间
********************************/
void keyscan()
{
uint i;
if(key1==0)
{
delay1ms(5);
if(key1==0)
{
while(!key1);
gn_flag++;
if(gn_flag==8)
{
gn_flag=0;
write_1602_cmd(0x0c);
write_ds1302(0x8e,0x00);
for(i=0;i<7;i++)
{
write_ds1302(time_wadd[i],time_shuzhi[i]);
}
write_ds1302(0x8e,0x10);
}
switch(gn_flag)
{
case 1 : write_1602_cmd(0x80+0x40+11);
write_1602_cmd(0x0f);break;
case 2 : write_1602_cmd(0x80+0x40+8);break;
case 3 : write_1602_cmd(0x80+0x40+5);break;
case 4 : write_1602_cmd(0x80+14);break;
case 5 : write_1602_cmd(0x80+10);break;
case 6 : write_1602_cmd(0x80+7);break;
case 7 : write_1602_cmd(0x80+4);break;
default: break;
}
}
}
if(key2==0)
{
delay1ms(5);
if(key2==0)
{
while(!key2);
switch(gn_flag)
{
case 1 : time_shuzhi[6]++;
time_bcd(6);
if(time_shuzhi[6]==0x59) time_shuzhi[6]=0 ;
xieshijian2(10,time_shuzhi[6]);
write_1602_cmd(0x80+0x40+11);
break;
case 2 : time_shuzhi[5]++;
time_bcd(5);
if(time_shuzhi[5]==0x59) time_shuzhi[5]=0 ;
xieshijian2(7,time_shuzhi[5]);
write_1602_cmd(0x80+0x40+8);
break;
case 3 : time_shuzhi[4]++;
time_bcd(4);
if(time_shuzhi[4]==0x12) time_shuzhi[4]=0 ;
xieshijian2(4,time_shuzhi[4]);
write_1602_cmd(0x80+0x40+5);
break;
case 4 : time_shuzhi[3]++;
time_bcd(3);
if(time_shuzhi[3]==0x8) time_shuzhi[3]=1 ;
xiexingqi(12,time_shuzhi[3]);
write_1602_cmd(0x80+14);
break;
case 5 : time_shuzhi[2]++;
time_bcd(2);
if(time_shuzhi[2]==0x30) time_shuzhi[2]=0 ;
xieshijian1(9,time_shuzhi[2]);
write_1602_cmd(0x80+10);
break;
case 6 : time_shuzhi[1]++;
time_bcd(1);
if(time_shuzhi[1]==0x13) time_shuzhi[1]=1 ;
xieshijian1(6,time_shuzhi[1]);
write_1602_cmd(0x80+7);
break;
case 7 : time_shuzhi[0]++;
time_bcd(0);
if(time_shuzhi[6]==0x50) time_shuzhi[6]=0 ;
xieshijian1(3,time_shuzhi[0]);
write_1602_cmd(0x80+4);
break;
default : break;
}
}
}
}
小弟不才参照这下面的程序(经运行,下面程序关闭后,时钟还在走,开机继续)进行检查,但却找不到问题所在望高手解答。最好能小弟上面的程序改下,以实现功能。万分感谢~
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ADDATA P0
sbit RS=P2^6;
sbit RW= P2^5;
sbit E=P2^7;
sbit Acc0=ACC^0;
sbit Acc7=ACC^7;
sbit Ds1302_clk=P3^6;
sbit Ds1302_rst=P3^5;
sbit Ds1302_DQ=P3^4;
//uchar code time1[]={"time:"};
//uchar code data1[]={"date:"};
//uchar code week1[]={"week:"};
uchar data timestr[8];
uchar data datestr[8];
//uchar data weekstr[3];
void delayms(uint tt )
{
uint i;
while( tt-- )
for(i=113;i>0;i--);
}
//*************check busy**************//
void lcd_busy()
{
RS= 0;
RW = 1;
E = 1;
_nop_();
_nop_();
_nop_();
_nop_();
while(P0&0x80);
}
void write_date( uchar dat)//写数据
{
lcd_busy() ;
RS=1;
RW=0;
E=1;
P0=dat;
delayms(1);
E=0;
delayms(2);
}
void write_com(uchar dat)//写指令
{
lcd_busy();
RS=0;
RW=0;
E=1;
P0=dat;
delayms(1);
E=0;
delayms(2);
}
void write_string(uchar *p)// 写数组,
{
uchar i=0;
while(*(p+i)!='\0')
{
write_date(*(p+i));
i++;
}
}
void Init_LCD()//初始化
{
write_com(0x38); //设置几行几 6
write_com(0x0f);//光标 4
write_com(0x06); //光标自动移动
write_com(0x01);//清黑框
}
//****************** 1302 PIN defined***********//
//#define AM(X) X
//#define PM(X) (X+12)
#define Ds1302_SEC 0x81
#define Ds1302_MIN 0x82
#define Ds1302_HOUR 0x84
#define Ds1302_WEEK 0x8a
#define Ds1302_DAY 0x86
#define Ds1302_MON 0x88
#define Ds1302_YEAR 0x8c
void Ds1302InputByte(uchar d) //* input a byte to ds1302******//
{
uchar i;
ACC=d;
for (i=8;i>0;i--)
{
Ds1302_DQ=Acc0;
Ds1302_clk=1;
Ds1302_clk=0;
ACC=ACC>>1;
}
}
uchar Ds1302OutputByte(void) //* output a byte to ds1302******//
{
uchar i;
for(i=8;i>0;i--)
{
ACC=ACC>>1;
Acc7=Ds1302_DQ;
Ds1302_clk=1;
Ds1302_clk=0;
}
return (ACC);
}
uchar Ds1302_RD(uchar ucAddr)
{
uchar Data;
Ds1302_rst=0;
Ds1302_clk=0;
Ds1302_rst=1;
Ds1302InputByte(ucAddr|0x01);
Data=Ds1302OutputByte();
Ds1302_clk=1;
Ds1302_rst=0;
return(Data);
}
void Ds_1302WR(uchar ucAddr, uchar ucData)
{
Ds1302_rst=0;
Ds1302_clk=0;
Ds1302_rst=1;
Ds1302InputByte(ucAddr);
Ds1302InputByte(ucData);
Ds1302_clk=1;
Ds1302_rst=0;
}
void Init_DS1302()
{
uchar second=Ds1302_RD(Ds1302_SEC);
if(second&0x80)
{
Ds_1302WR(0x8e,0x00);
Ds_1302WR(0x8c,0x12);
Ds_1302WR(0x88,0x05);
Ds_1302WR(0x86,0x13);
Ds_1302WR(0x8a,0x28);
Ds_1302WR(0x84,0x20);
Ds_1302WR(0x82,0x12);
Ds_1302WR(0x80,0x10);
Ds_1302WR(0x8e,0x80);
}
}
uchar bcd_to_bin(uchar bcd)
{
uchar a;
a=bcd;
a>>=4;
a*=10;
bcd&=0x0f;
a+=bcd;
return a;
}
void gettime1()
{
uchar x; uchar y;
x= Ds1302_RD(Ds1302_HOUR);
y= bcd_to_bin(x);
timestr[0]=y/10+'0';
timestr[1]=y%10+'0';
timestr[2]=':';
x=Ds1302_RD(Ds1302_MIN);
y=bcd_to_bin(x);
timestr[3]=y/10+'0';
timestr[4]=y%10+'0';
timestr[5]=':';
x=Ds1302_RD(Ds1302_SEC);
y= bcd_to_bin(x);
timestr[6]=y/10+'0';
timestr[7]=y%10+'0';
timestr[8]='\0';
}
void gettime2()
{
uchar x; uchar y;
x=Ds1302_RD(Ds1302_YEAR);
y=bcd_to_bin(x);
datestr[0]=y/10+'0';
datestr[1]=y%10+'0';
datestr[2]='-';
x=Ds1302_RD(Ds1302_MON);
y=bcd_to_bin(x);
datestr[3]=y/10+'0';
datestr[4]=y%10+'0';
datestr[5]='-';
x=Ds1302_RD(Ds1302_DAY);
y=bcd_to_bin(x);
datestr[6]=y/10+'0';
datestr[7]=y%10+'0';
datestr[8]='\0';
}
void Show_Time() //我用的是12864,用1602 修改DDRAM地址即可
{
gettime1();
write_com(0xc4);
write_string( timestr);
gettime2();
write_com(0x84);
write_string(datestr);
}
void main()
{
Init_LCD();
Init_DS1302();
//Ds_1302WR(0xbf);
while(1)
{
Show_Time();
//Ds_1302WR(0x91,0x15);
}
}