xiaoyan911 发表于 2011-11-23 18:59:13

51单片机之时钟芯片DS1302的使用

#include"reg52.h"
#define uint unsigned int
#define uchar unsigned char
uchar second,minute,hour,day,month,week,year;
sbit wr=P2^5;
sbit rs=P2^6;
sbit lcde=P2^7;

sbit ds1302=P3^4;
sbit rst=P3^5;
sbit sclk=P3^6;

uchar code table1[]="   11-04-19";
uchar code table2[]=" 23:59:50 week:7";
void delay(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}

void write_com(uchar com)                   //写命令
{
        rs=0;
        lcde=0;
        P0=com;
        delay(2);
        lcde=1;
        delay(2);
        lcde=0;               
}

void write_dat(uchar dat)                          //写数据
{
        rs=1;
        lcde=0;
        P0=dat;
        delay(2);
        lcde=1;
        delay(2);
        lcde=0;               
}

void init1602()
{
        uchar num;
        wr=0;
        write_com(0x38); //显示模式设置
        write_com(0x0c);
        write_com(0x06);
        write_com(0x01);//清屏
        write_com(0x80);
        for(num=0;num<11;num++)
        {
                write_dat(table1);
                delay(1);       
        }
        write_com(0x80+0x40);
        for(num=0;num<16;num++)
        {
                write_dat(table2);
                delay(1);
        }               
}

void write1302(uchar dat)
{
        uchar i;
        for(i=0;i<8;i++)
        {
                sclk=0;
                ds1302=dat&0x01;           //当SCLK为0时把数据放在数据口
                delay(1);
                sclk=1;                                   //SCLK为高电平时把数据写进去
                delay(1);
                dat>>=1;
        }

}

uchar read1302()
{
        uchar i,dat;
        for(i=0;i<8;i++)
        {
                dat>>=1;
                sclk=1;                               
                delay(1);
                sclk=0;
                if(ds1302==1)          //当SCLK在下降沿的时候把数据读走
                dat=dat|0x80;
                delay(1);
                               
        }

        return dat;
}

void writeset1302(uchar cmd,uchar dat)                       //一次写两个字节,一个为控制字节,另一个为数据。注意写数据时必须打开写保护寄存器
{
        sclk=0;                                                                                   //开始比RST先为低电平
    rst=0;
        rst=1;
        delay(1);
        write1302(cmd);
        write1302((dat/10)<<4|(dat%10));                   //将10进制转化为压缩的BCD码,传输时为BCD码
        sclk=0;               
        rst=0;
}

uchar readset1302(uchar cmd)
{
        uchar dat,datH,datL,temp;
        rst=0;
        rst=1;
        sclk=0;
        delay(1);
        write1302(cmd);
        dat=read1302();
        sclk=0;       
        rst=0;
        datH=dat/16;                           //将压缩的BCD码转换为十进制书相当于左移4位
        datL=dat%16;                           //
        temp=datH*10+datL;                   //
        return (temp);
}

void init1302()
{
                writeset1302(0x8e,0x00);        ///将写保护寄存器打开允许写操作
                writeset1302(0x80,50);        ///写秒和开启时钟
                writeset1302(0x82,59);        ///分
                writeset1302(0x84,23);                ///        时
                writeset1302(0x86,19);               ///日
                writeset1302(0x88,4);               ///月
                writeset1302(0x8a,7);               ///周
                writeset1302(0x8c,11);                ///           年
                writeset1302(0x90,0xa5);      ///打开充电功能,选择2K电阻方式充电
                writeset1302(0x8e,0x80);   ///写保护寄存器,写入保护指?

}

void display1602(uchar dat)
{
        uchar shi,ge;
        shi=dat/10;
        ge=dat%10;
        write_dat(0x30+shi);
        write_dat(0x30+ge);
}

void time()                                       //显示日期和时期
{
        second=readset1302(0x81);
        write_com(0x80+0x40+7);
        display1602(second);

        minute=readset1302(0x83);
        write_com(0x80+0x40+4);
        display1602(minute);

        hour=readset1302(0x85);
        write_com(0x80+0x40+1);
        display1602(hour);

        day=readset1302(0x87);
        write_com(0x80+9);
        display1602(day);

        month=readset1302(0x89);
        write_com(0x80+6);
        display1602(month);

        week=readset1302(0x8b)*10;
        write_com(0x80+0x40+15);
        display1602(week);

        year=readset1302(0x8d);
        write_com(0x80+3);
        display1602(year);       
}
void main()
{
        init1602();
//        init1302();
        while(1)
        {
                time();               
                       
        }

}

qun453176385 发表于 2012-1-4 16:03:11

mark

lidreamer 发表于 2012-1-5 23:36:19

恩,不错,我写过12887的并且是用数码管显示的

hzy3774 发表于 2012-1-13 12:15:50

好,学习了

dcqq88 发表于 2012-7-23 16:23:07

太感谢阿!好好学习....

beijinggood2008 发表于 2012-7-25 18:53:20

我现在也在玩DS1302,有个疑问请教一下LZ   
time()
       {
         second=readset1302(0x81);
      write_com(0x80+0x40+7);
      display1602(second);

      ................
      }
      这里面读出秒数据后立即显示,如何来保证你下一次显示秒的时候是一秒钟后呢?
      希望向LZ学习一下!

bbxyliyang08 发表于 2012-11-10 20:02:41

beijinggood2008 发表于 2012-7-25 18:53 static/image/common/back.gif
我现在也在玩DS1302,有个疑问请教一下LZ   
time()
       {


是这样的

bbxyliyang08 发表于 2012-11-11 11:47:07

程序有问题啊,writeset1302(0x8e,0x80);   你这个函数是实现10进制数转化BCD码?

lklhzu 发表于 2012-11-12 16:40:41

本帖最后由 lklhzu 于 2012-11-13 09:56 编辑

bbxyliyang08 发表于 2012-11-11 11:47 static/image/common/back.gif
程序有问题啊,writeset1302(0x8e,0x80);   你这个函数是实现10进制数转化BCD码?

这个是加写保护,写保护加上后就禁止写入了。但是他这个writeset1302()函数里面已经将十进制转换为BCD码了,所以
writeset1302(0x8e,0x00);      ///将写保护寄存器打开允许写操作
writeset1302(0x90,0xa5);      ///打开充电功能,选择2K电阻方式充电
writeset1302(0x8e,0x80);   ///写保护寄存器,写入保护指?
这几个命令应该都失效了吧!

bbxyliyang08 发表于 2012-11-12 19:56:33

你这个使时钟怎么不搞调时功能?writeset1302(uchar cmd,uchar dat) 不是将dat 10进制转化为压缩的BCD码,传输时为BCD码
而你0x80是十六进制啊?

zjsdlt2013 发表于 2013-6-21 22:57:43

显示正常,但时间为什么不跑啊?哪里有问题了?
页: [1]
查看完整版本: 51单片机之时钟芯片DS1302的使用