关于AT24c02做的时钟,有点小问题不懂,请教下大侠们
我是个新手,搞了大半天,还是不知道问题出现在哪里?液晶上时间显示的是乱码,哪位大侠帮帮忙,看下我的程序问题出现在哪里?源程序如下
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
bit write=0;
sbit SDA=P2^0;
sbit SCL=P2^1;
sbit dula=P2^6;//申明U1锁存器的锁存端
sbit wela=P2^7;
sbit rs=P3^5;//液晶数据命令选择端
sbit lcden=P3^4;//液晶使能端
sbit s1=P3^0;//矩阵键盘当独立键盘使用不能用独立键盘的原因是P3^4,P^35已经被占用了
sbit s2=P3^1;//
sbit s3=P3^2;//
sbit rd=P3^7;//需置0(和独立键盘类似了)
sbit beep=P2^3;
uchar count,s1num;
char miao,shi,fen;//必须注意这三个变量一定要是全局的char型(miao==-1才符合此类型)变量而不是uchar型
uchar code table[]="2007-7-30 MON";
uchar code table1[]=" 00:00:00";
void delay0()
{;;}
void init_24c02()
{
SDA=1;//初始化时总线释放全部置为1
delay0();
SCL=1;
delay0();
}
void start()//启动信号
{
SDA=1;
delay0();
SCL=1;//SCL在高电平期间,SDA一个下降沿启动信号
delay0();
SDA=0;
delay0();
}
void respons() reentrant//应答信号
{
uchar i;
SCL=1;
while((SDA==1)&&(i<250))
i++;
SCL=0;//第九个时钟再拉低
delay0();
}
void stop()//停止信号
{
SDA=0;
delay0();
SCL=1;
delay0();
SDA=1;
delay0();
}
void writebyte(uchar date )//写一个字节
{
uchar temp,i;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
SCL=0;
delay0();
SDA=CY;
delay0();
SCL=1;
delay0();
}
SCL=0;
delay0();
SDA=1;//总线释放,目的是读取应答信号
delay0();
}
uchar readbyte()//读一个字节
{
uchar i,k;
SCL=0;
delay0();
SDA=1;
for(i=0;i<8;i++)
{
SCL=1;
delay0();
k=(k<<1)|SDA;
SCL=0;
delay0();
}
return k;
}
void write_add(uchar address,uchar date)//指定地址address写一个数据date(参考时序)
{
start();
writebyte(0xa0);//器件地址
respons();
writebyte(address);//器件内部储存器地址
respons();
writebyte(date);
respons();
stop();
}
uchar read_add(uchar address)//指定地址address读取一个数据(参考时序)
{
uchar date;
start();
writebyte(0xa0);
respons();
writebyte(address);
respons();
start();
writebyte(0xa1);
respons();
date=readbyte();
stop();
return date;
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void di()
{
beep=0;
delay(100);
beep=1;
}
void write_com(uchar com)//写指令函数
{
rs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date)//写数据函数
{
rs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_sfm(uchar add,uchar date)//时分秒显示
{
uchar shi,ge;
shi=date/10;//若date=35则shi=3
ge=date%10;//ge=5
write_com(0x80+0x40+add);
write_date(0x30+shi);//ASCII码0x30+shi=0x33(即为十进制的3)
write_date(0x30+ge);//即为十进制的5
}
void init()//初始化函数
{
uchar num;
dula=0;
wela=0;
lcden=0;
miao=0;
fen=0;
shi=0;
init_24c02();
write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口
write_com(0x0c);//设置开显示,不显示光标
write_com(0x06);//写一个字符后地址指针加1
write_com(0x01);//显示清0,数据指针清0
write_com(0x80);//先将数据指针定段到第一行第一个字符
for(num=0;num<15;num++)//液晶显示初始状态
{
write_date(table);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<12;num++)//液晶显示初始状态
{
write_date(table1);
delay(5);
}
miao=read_add(1);//首次上电从AT24c02中读取出存储的数据
fen=read_add(2);
shi=read_add(3);
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void keyscan()//键盘扫描函数
{
rd=0;//置0,即接地(根据独立键盘原理图)
if(s1==0)
{
delay(5);//去抖
if(s1==0)//按两下tab(标注的意思目的让if(s1num!=0)和该行是并排的)
{
s1num++;//s1按下去的次数为s1num,为全局变量
while(!s1);//等待键盘释放
di();
if(s1num==1)//按1次让秒闪烁
{
TR0=0;
write_com(0x80+0x40+10);//将数据指针定位到秒的位置
write_com(0x0f);//光标闪烁
}
}
if(s1num==2)//按第二次让分闪烁
{
write_com(0x80+0x40+7);//将数据指针定位到分的位置
}
if(s1num==3)//按第三次让时闪烁
{
write_com(0x80+0x40+4);//将数据指针定位到时的位置
}
if(s1num==4)
{
s1num=0;//清0,为了下次从0开始加
write_com(0x0c);//不显示光标
TR0=1;//时钟继续走,开定时器1
}
}
if(s1num!=0)
{
if(s2==0)
{
delay(5);//消抖
if(s2==0)
{
while(!s2);//等待键盘释放,弱不等待会出现问题
di();
if(s1num==1)//s1键按了一次即光标在秒的位置闪烁
{
miao++;
if(miao==60)
miao=0;
write_sfm(10,miao);//写秒并显示,此时指针又加1了,和下面一条语句位置不能反
write_com(0x80+0x40+10);//上一条语句指针加1了,故需要将数据指针定位到秒的位置,下次再次使用
write_add(1,miao);
}
if(s1num==2)//s2键按了一次即光标在分的位置闪烁
{
fen++;
if(fen==60)
fen=0;
write_sfm(7,fen);//写分并显示,此时指针又加1了,和下面一条语句位置不能反
write_com(0x80+0x40+7);//上一条语句指针加1了,故需要将数据指针定位到分的位置,下次再次使用
write_add(2,fen);
}
if(s1num==3)//s3键按了一次即光标在是的位置闪烁
{
shi++;
if(shi==24)
shi=0;
write_sfm(4,shi);//写时并显示,此时指针又加1了,和下面一条语句位置不能反
write_com(0x80+0x40+4);//上一条语句指针加1了,故需要将数据指针定位到时的位置,下次再次使用
write_add(3,shi);
}
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
di();
if(s1num==1)
{
/* if(miao==0)
{
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}*/
miao--;//顺序不能乱
if(miao==-1)//和秒加的时候不一样,若miao==0,会直接从01跳到59而不是跳到00
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
write_add(1,miao);
}
if(s1num==2)
{
fen--;
if(fen==-1)//和分加的时候不一样,要注意
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+7);
write_add(2,fen);
}
if(s1num==3)
{
shi--;
if(shi==-1)//和分加的时候不一样,要注意
shi=23;
write_sfm(4,shi);
write_com(0x80+0x40+4);
write_add(3,shi);
}
}
}
}
}
void main()
{
init();
while(1)
{
keyscan();
}
while(1);
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==18)
{
count=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
write_sfm(4,shi);
write_add(3,shi);
}
write_sfm(7,fen);
write_add(2,fen);
}
write_sfm(10,miao);
write_add(1,miao);
}
}
有没有人指导下小弟哈 有没有人指导下小弟哈{:sweat:} 显示也做到中断内 lee345 发表于 2012-7-27 12:03 static/image/common/back.gif
显示也做到中断内
怎么个做法呢,能不能具体点呢 在时间中断内就设几个更新显示的位标志,更新显示工作转到大循环中 AT24C02可以做时钟?第一次听说~ nongxiaoming 发表于 2012-7-27 15:31 static/image/common/back.gif
AT24C02可以做时钟?第一次听说~
不是做时钟,是保存收据 1284740313 发表于 2012-7-27 17:16 static/image/common/back.gif
不是做时钟,是保存收据
保存啥数据呢............ raxb 发表于 2012-7-27 17:35 static/image/common/back.gif
保存啥数据呢............
实时数据啊,当前你的液晶显示08:20:15;掉电之后还是这个时间,而不是初始时间什么的 1284740313 发表于 2012-7-28 08:31 static/image/common/back.gif
实时数据啊,当前你的液晶显示08:20:15;掉电之后还是这个时间,而不是初始时间什么的 ...
时间就是要一直走啊,都不走了保存有什么意义呢,反正再次上电还要再调 在加上DS1302啊 at24c04是EEPROM。。。 1284740313 发表于 2012-7-27 14:53 static/image/common/back.gif
怎么个做法呢,能不能具体点呢
void timer1() interrupt 3//定时1ms
{
TH1=0xf8;
TL1=0xcd;
ms2_flag=1; //用于数码管显示
ms2_cnt++;
if(ms2_cnt>=5)
{
ms2_cnt=0;
ms10_flag=1;//用于键扫描
if(++ms10_cnt>=50)
{
ms10_cnt=0;
ms500_flag=~ms500_flag;
}
}
}
while(1)
{
if(ms2_flag)
{
ms2_flag=0;
LedBitCnt++;
if(LedBitCnt>7)
{
LedBitCnt=0;
}
time_to_disbuff();
disp();
}
}
页:
[1]