现在的位置: 首页 > 综合 > 正文

单片机 DS1302 痛苦的调试过程,把我的经验教训分享给大家,希望能给后来者一点帮助

2012年12月29日 ⁄ 综合 ⁄ 共 4736字 ⁄ 字号 评论关闭

原文地址::http://topic.csdn.net/u/20100904/08/736d7397-0ea6-4e12-a859-c1c4775b1ac6.html

 

 

这个是我现在用的程序,还没加闹钟,想加的话也容易,程序有点儿冗余,可能是我的函数写的不够好,不过不管怎么说总算是能用啦,而且我想的功能已经全部实现了,所以拿出来晒晒,希望对还在郁闷的有些帮助,呵呵
我写的过程中遇到的问题:
1,每次写两个字节之后都要把RST=0,SCLK=0,RST=1重写一遍的,我原来的时候没有注意到,详细的请看程序里面就可以看得出来
2,年的位置和周的位置不要搞反了,我就是搞反了,就这个问题就想了几天想不明白,写进去的数和显示出来的数不一样啊,我那个郁闷啊,后来在看技术手册的时候终于看到了,所以大家在写程序的时候一定要好好看技术手册,认真的看,一遍遍的看
3,每次修改一次时间都要从1302里面写一次,这个可能是我的程序的原因,在最后的时候写不行,不知道是为什么,有哪位知道也可以告诉我,随时欢迎
4,不知道为什么我用的板子上写保护不管用,就是说不管我写不写保护都可以,甚至我在写数据之前打开写保护,还可以写进去数据,这个问题我也很是郁闷,大家有哪位能在程序里看出些端倪的也可以随时告诉我,谢谢
下面是代码:
//
//
//1为功能键,2为增加时间键,3为减少时间键
#include<reg52.h>
#include<yj1602.h>
#include<jp.h>

#define uchar unsigned char

sbit sclk=P1^5;
sbit io=P1^6;
sbit rst=P1^7;

uchar time[]={0x00,0x42,0x08,0x04,0x09,0x06,0x10};
uchar timetmp[7];
uchar MAX[]={59,59,23,31,12,7,99};
uchar MINX[]={0,0,0,1,1,1,1};
uint readdata[7];
uchar sec,min,hour,day,month,week,year;
uchar keynum,ss;

void write(uchar date) //写一个字节
{
uchar i;
for(i=0;i<8;i++)
{
io=date&0x01;
sclk=1;sclk=0;
date=date>>1;
}
}
uchar read() //读一个字节
{
uchar shuju,i;
for(i=0;i<8;i++)
{
shuju=shuju>>1;
sclk=0;
if(io)
shuju=shuju|0x80;
sclk=1;
}
return shuju;
}
void writebyte(uchar add,date) //写时间的一个单位(分/秒/时/年/月/日/周)
{
rst=0;sclk=0;rst=1;
write(0x8e);
write(0x00);
rst=0;sclk=0;rst=1;
write(add);
write(date);
rst=0;sclk=0;rst=1;
write(0x8e);
write(0x80);
rst=0;sclk=1;
}
void writetime() //初始化时间
{
uchar i,j=0x80;
for(i=0;i<7;i++)
{
writebyte(j,time[i]);
j+=2;
}
}
uchar readbyte(add) //读一个单位时间(分/秒/时/年/月/日/周)
{
uchar date;
rst=0;sclk=0;rst=1;
write(add);
date=read();
rst=0;sclk=1;
return date;
}
void readtime() //读取时间
{
uchar i,j=0x81;
for(i=0;i<7;i++)
{
readdata[i]=readbyte(j);
j+=2;
}
}
void process() //数制转换
{ uchar i;
for(i=0;i<7;i++)
{
readdata[i]=(readdata[i]>>4)*10+(readdata[i]&0x0f);
}
}

void display() //显示函数
{
display_1602N(0,1,2);
display_1602N(1,1,0);
display_1602N(2,1,year/10);
display_1602N(3,1,year%10);
display_1602S(4,1,"-"); 
display_1602N(5,1,month/10);
display_1602N(6,1,month%10);
display_1602S(7,1,"-"); 
display_1602N(8,1,day/10);
display_1602N(9,1,day%10);
display_1602S(11,1,"WEEK");
display_1602N(15,1,week);
display_1602S(1,2,"TIME");
display_1602S(5,2,":");
display_1602N(6,2,hour/10);
display_1602N(7,2,hour%10);
display_1602S(8,2,":");
display_1602N(9,2,min/10);
display_1602N(10,2,min%10);
display_1602S(11,2,":");
display_1602N(12,2,sec/10);
display_1602N(13,2,sec%10);
}
void timeout() //提取时间
{
sec=readdata[0];
min=readdata[1];
hour=readdata[2];
day=readdata[3];
month=readdata[4];
week=readdata[5];
year=readdata[6];
}
void shanshuo2(uchar add,time) //1602第二行闪烁函数
{
write_com(0x80+0x40+add);
write_date(0x10);
write_com(0x80+0x40+add-1);
write_date(0x10);
delay(100);
display_1602N(add,2,time%10);
display_1602N(add-1,2,time/10);
delay(100);
}
void shanshuo1(uchar add,time) //1602第一行闪烁函数
{
write_com(0x80+add); //当前位什么也不显
write_date(0x10);
write_com(0x80+add-1);
write_date(0x10);
delay(100); //延时
display_1602N(add,1,time%10); //显示时间
display_1602N(add-1,1,time/10);
delay(100); //延时
}
void zj(uchar num) //增减函数
{
switch(keynum)
{
case 1:ss++;break; //如果是1,则进入下一位的调整
case 2:{ //如果是2,则当前闪烁的位加1
timetmp[num]++;
if(timetmp[num]>MAX[num]) //如何超过了闪烁位的最大值,返回最小值
timetmp[num]=MINX[num];
}break;
case 3:{ //如果是3,则当前闪烁的位减1
timetmp[num]--;
if(timetmp[num]<MINX[num]) //如何超过了闪烁位的最小值,返回最大值
timetmp[num]=MAX[num];
}break;
default:break;
}
}
void jpaction() //调时操作
{
while(ss<7)
{  

while(ss==0) //调秒
{
key=0;
timetmp[0]=readbyte(0x81)/16*10+readbyte(0x81)%16; //从1302中取出时间
shanshuo2(13,timetmp[0]); //显示时间并闪烁
keynum=jiance(); //按键检测
zj(0); //对时间进行操作
writebyte(0x80,timetmp[0]/10*16+timetmp[0]%10); //把调整过的时间写到1302中
}  
while(ss==1) //调分
{
key=0;
timetmp[1]=readbyte(0x83)/16*10+readbyte(0x83)%16; //同上
shanshuo2(10,timetmp[1]);
keynum=jiance();
zj(1);
writebyte(0x82,timetmp[1]/10*16+timetmp[1]%10);
}

while(ss==2) //调时
{
key=0;
timetmp[2]=readbyte(0x85)/16*10+readbyte(0x85)%16; //同上
shanshuo2(7,timetmp[2]);
keynum=jiance();
zj(2);
writebyte(0x84,timetmp[2]/10*16+timetmp[2]%10);
}
while(ss==3) //调日
{
key=0;
timetmp[3]=readbyte(0x87)/16*10+readbyte(0x87)%16; //同上
shanshuo1(9,timetmp[3]);
keynum=jiance();
zj(3);
writebyte(0x86,timetmp[3]/10*16+timetmp[3]%10);
}
while(ss==4) //调月
{
key=0;
timetmp[4]=readbyte(0x89)/16*10+readbyte(0x89)%16;
shanshuo1(6,timetmp[4]);
keynum=jiance();
zj(4);
writebyte(0x88,timetmp[4]/10*16+timetmp[4]%10);
}
while(ss==5) //调周
{
key=0;
timetmp[5]=readbyte(0x8b)/16*10+readbyte(0x8b)%16; //同上
shanshuo1(15,timetmp[5]);
keynum=jiance();
zj(5);
writebyte(0x8a,timetmp[5]/10*16+timetmp[5]%10);
}
while(ss==6) //调年
{
key=0;
timetmp[6]=readbyte(0x8d)/16*10+readbyte(0x8d)%16; //同上
shanshuo1(3,timetmp[6]);
keynum=jiance();
zj(6);
writebyte(0x8c,timetmp[6]/10*16+timetmp[6]%10);
}  
}
}  
 
void main()
{
init_1602(); //初始化1602
writetime(); //首次上电,往1302里面写时间
while(1)
{
readtime(); //从1302中读时间
process(); //把取出的时间(BCD码)转化为十进制
timeout(); //把时间从数组中提取出来
display(); //在1302上显示时间
keynum=jiance(); //检测按键是不是要调整时间
if(keynum==1)
{
ss=0;
jpaction(); //相应调时操作
writebyte(0x80,timetmp[0]/10*16+timetmp[0]%10); //重写秒,把秒写回到调之前的位置
ss=0;
key=0;
}  

  }

}

抱歉!评论已关闭.