1284740313 发表于 2012-7-27 10:48:48

关于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);
                }       
}

1284740313 发表于 2012-7-27 11:10:32

有没有人指导下小弟哈

1284740313 发表于 2012-7-27 11:43:14

有没有人指导下小弟哈{:sweat:}

lee345 发表于 2012-7-27 12:03:00

显示也做到中断内

1284740313 发表于 2012-7-27 14:53:32

lee345 发表于 2012-7-27 12:03 static/image/common/back.gif
显示也做到中断内

怎么个做法呢,能不能具体点呢

lee345 发表于 2012-7-27 15:20:58

在时间中断内就设几个更新显示的位标志,更新显示工作转到大循环中

nongxiaoming 发表于 2012-7-27 15:31:15

AT24C02可以做时钟?第一次听说~

1284740313 发表于 2012-7-27 17:16:38

nongxiaoming 发表于 2012-7-27 15:31 static/image/common/back.gif
AT24C02可以做时钟?第一次听说~

不是做时钟,是保存收据

raxb 发表于 2012-7-27 17:35:20

1284740313 发表于 2012-7-27 17:16 static/image/common/back.gif
不是做时钟,是保存收据

保存啥数据呢............

1284740313 发表于 2012-7-28 08:31:13

raxb 发表于 2012-7-27 17:35 static/image/common/back.gif
保存啥数据呢............

实时数据啊,当前你的液晶显示08:20:15;掉电之后还是这个时间,而不是初始时间什么的

raxb 发表于 2012-7-28 11:55:14

1284740313 发表于 2012-7-28 08:31 static/image/common/back.gif
实时数据啊,当前你的液晶显示08:20:15;掉电之后还是这个时间,而不是初始时间什么的 ...

时间就是要一直走啊,都不走了保存有什么意义呢,反正再次上电还要再调

秋之舞者 发表于 2012-7-31 10:08:49

在加上DS1302啊

aleyn 发表于 2012-7-31 10:14:09

at24c04是EEPROM。。。

bbxyliyang08 发表于 2012-11-12 00:19:30

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]
查看完整版本: 关于AT24c02做的时钟,有点小问题不懂,请教下大侠们