搜索
bottom↓
回复: 6

ds1302 电子时钟

[复制链接]

出0入0汤圆

发表于 2012-11-11 17:15:47 | 显示全部楼层 |阅读模式
#include<reg51.h>
#define uint8 unsigned char
#define uint16 unsigned int
sbit RST=P1^7;
sbit SDA=P3^5;
sbit SCK=P1^6;
uint8 LedBitCnt; //LedBitCnt控制数码管的位选
uint8 ms2_flag; //2ms数码管动态扫描时标消息
uint8 ms10_flag,ms500_flag;
uint8 ms2_cnt,ms10_cnt,count,s1num;
uint8 dis_buff[8]={0};
uint8 shi=12,fen=23,miao=56;
uint8 code SegTab[]={0x3f,0x06,0x5b,0x4f,
                                        0x66,0x6d,0x7d,0x07,
                                        0x7f,0x6f,0x40,0x00};
sbit ADDR0 = P2^0;//74hc138的输入控制端A
sbit ADDR1 = P2^1;//74hc138的输入控制端B
sbit ADDR2 = P2^2;//74hc138的输入控制端C
sbit adjust=P3^2;
sbit add=P3^3;
sbit sub=P3^4;

//常数宏
#define DS1302_SECOND_WRITE 0x80//写时钟芯片的寄存器位置
#define DS1302_MINUTE_WRITE 0x82
#define DS1302_HOUR_WRITE   0x84
#define DS1302_SECOND_READ  0x81//读时钟芯片的寄存器位置
#define DS1302_MINUTE_READ  0x83
#define DS1302_HOUR_READ  0x85


void reset_ds1302(void)
{
        RST=0;
        SCK=0;
        RST=1;
}

/****************************
*名称:write_ds1302_byte
*说明:无
*功能: 写入8bit数据
*调用: 无
*输入:dat:要写入的数据
*输出:无
*****************************/
void write_ds1302_byte(uint8 dat)
{
        uint8  i;
        SCK=0;//初始化时钟线置为0
        for(i=0;i<8;i++)//开始传输8个字节的数据
        {
                SDA=dat&0x01;//取最低位,注意DS1302的数据
                     //和地址都是从最低位开始传输的
                SCK=1;//时钟线拉高,制造上升沿,SDA数据被传输
                SCK=0;  //时钟线拉低,为下个上升沿做准备
                dat>>=1;//数据右移一位,准备传输的下一位
        }
}
/****************************
*名称:read_ds1302_byte
*说明:无
*功能: 读取8bit数据
*调用: 无
*输入:dat:读取的数据
*输出:无
*****************************/
uint8 read_ds1302_byte(void)
{
        uint8  i ,dat=0;
    for (i=0;i<8;i++)
        {
                dat >>=1;
                if(SDA)
        dat|=0x80;
                SCK=1;
                SCK=0;//制造下降沿
    }
                return dat;
}

/****************************
*名称:write_ds1302
*说明:先写地址,后写数据
*功能:向addr相应地址中写一个字节的数据
*调用: write_ds1302_byte()
*输入:addr:要写入的控制字,dat:要写入的数据
*输出:无
*****************************/
void write_ds1302(uint8 addr,uint8 dat)
{
                reset_ds1302();
            write_ds1302_byte(addr);
                write_ds1302_byte((dat/10)<<4|(dat%10));
       //将10进制转化为压缩的BCD码,传输时为BCD码
        SCK=1;//时钟线拉高
                RST=0;//读取结束,CE置0,结束数据的传输

}
/****************************
*名称:uint8 read_ds1302
*说明:先写地址,后读数据
*功能: 从addr相应地址中读取一个字节的数据
*调用: write_ds1302_byte(),read_ds1302_byte()
*输入:addr:要写入的控制字
*输出:dat:要写入的数据
*****************************/
uint8 read_ds1302(uint8 addr)
{
                uint8 dat,datH,datL,temp=0;
                reset_ds1302();
            write_ds1302_byte(addr);
        dat=read_ds1302_byte();
               
        SCK=1;
                RST=0;
                datH=dat/16;  //将压缩的BCD码转换为十进制相当于左移4位
        datL=dat%16;                           
        temp=datH*10+datL;
                return temp;//返回得到的时间/日期

}
/****************************
*名称:void Init_DS1302
*说明:给1302写一个初始值
*功能:
*调用: write_ds1302()
*输入:无
*输出:无
*****************************/
void Init_DS1302(void)
{
        write_ds1302(0x8e,0x00);//写保护关
        write_ds1302(DS1302_SECOND_WRITE,40);
        write_ds1302(DS1302_MINUTE_WRITE,59);
        write_ds1302(DS1302_HOUR_WRITE,23);//初始24小时模式
    write_ds1302(0x8e,0x80);//写保护开
}

void init()
{
        TMOD=0x01;
        TH1=0xf8;
        TL1=0xcd;
    ET0=1;
        TR1=1;
        ET1=1;                       
}
void time_to_disbuff(void)
{
       
                dis_buff[7]=miao%10;
                dis_buff[6]=miao/10;
            dis_buff[5]=10;
        dis_buff[4]=fen%10;
                dis_buff[3]=fen/10;
        dis_buff[2]=10;
        dis_buff[1]=shi%10;
                dis_buff[0]=shi/10;
  
}
void disp()
{
        P0=SegTab[dis_buff[LedBitCnt]];
        switch(LedBitCnt)
        {
                case 0:
                ADDR0=0;ADDR1=0;ADDR2=0;
                break;
                case 1:
                ADDR0=1;ADDR1=0;ADDR2=0;
                break;
                case 2:
                ADDR0=0;ADDR1=1;ADDR2=0;
                break;
                case 3:
                ADDR0=1;ADDR1=1;ADDR2=0;
                break;
                case 4:
                ADDR0=0;ADDR1=0;ADDR2=1;
                break;
                case 5:
                ADDR0=1;ADDR1=0;ADDR2=1;
                break;
                case 6:
                ADDR0=0;ADDR1=1;ADDR2=1;
                break;
                case 7:
                ADDR0=1;ADDR1=1;ADDR2=1;
                break;
        }

}

void main()
{
        Init_DS1302();
        init();
        EA=1;

        while(1)
        {
               
                        miao=read_ds1302(DS1302_SECOND_READ);
                        fen=read_ds1302(DS1302_MINUTE_READ);
                        shi=read_ds1302(DS1302_HOUR_READ);
                        if(ms2_flag)
              {
                     ms2_flag=0;
                     LedBitCnt++;
                    if(LedBitCnt>7)
                    {
                        LedBitCnt=0;
                    }
                    time_to_disbuff();
                    disp();
                  }       
        }

}
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;
                        }
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2012-11-11 17:25:21 | 显示全部楼层
成功读取DS1302的时间,现在在添加按键调时遇到了问题,在第一次按下调整键时候,停止走时,显示秒的两位数码管以1 Hz 频率闪烁;如果第二次按下调整键,则分开始闪烁,秒恢复正常显示;如果第三次按下调整键,则时开始闪烁,分恢复正常显示;如果第四次按下调整键,时恢复正常显示,开始走时。在数码管闪烁的时候,按下加或者减键可以调整相应的显示内容,按下加减时要把调整后的数据送到时钟寄存器中后,在读出来,还是直接显示?

出0入0汤圆

发表于 2012-11-11 21:33:00 | 显示全部楼层
一般是在进调整状态时,把当前时钟读到一个缓存中,调整时钟其实是在调整缓存中的数据,当调整完一起写入1302,并开始走时。调整期间,1302会按原时钟继续走时。
另外,你这个帖子放这个版不合适

出0入0汤圆

 楼主| 发表于 2012-11-11 23:17:06 | 显示全部楼层
sf49ers 发表于 2012-11-11 21:33
一般是在进调整状态时,把当前时钟读到一个缓存中,调整时钟其实是在调整缓存中的数据,当调整完一起写入13 ...

一般的时钟不是进入调时状态,都停止走时,我的功能键第一次按下,调整秒的,我要把秒从0x80中读出来,当按加时,秒++,在把这个值写进0x80,最后在送到数码管显示?

出0入0汤圆

发表于 2012-11-11 23:41:41 | 显示全部楼层
bbxyliyang08 发表于 2012-11-11 23:17
一般的时钟不是进入调时状态,都停止走时,我的功能键第一次按下,调整秒的,我要把秒从0x80中读出来,当 ...

干吗做这么麻烦,反正时钟不走了,中间往1302写有什么意义。
如果象pc界面那样,专门有个取消键,本次调整无效,按原时间走,你怎么办

出0入0汤圆

 楼主| 发表于 2012-11-12 00:02:16 | 显示全部楼层
void keyscan()
{
        if(adjust==0)
                {
                        delayms(10);
                        if(adjust==0)
                                {
                                        s1num++;
                                        while(!adjust);
                                        if(s1num==1)
                                        {
                                                flagm=1;
                                                TR0=0;
                                        }
                                }
                }
               
                        if(s1num==2)
                {
                        flagm=0;
                        flagf=1;
                }

         if(s1num==3)
                {
                        flagm=0;
                        flagf=0;
                        flags=1;
                }
        if(s1num==4)
        {
                TR0=1;
                flags=0;
                s1num=0;
        }
        if(adjust!=0)
                {
                        if(add==0)
                        {
                                delayms(10);
                                if(add==0)
                                {
                                        while(!add);
                                        if(s1num==1)
                                        {
                                                miao++;
                                                if(miao==60)
                                                        miao=0;
                                       
                                               
                                               
                                        }
                                        if(s1num==2)
                                        {
                                                fen++;
                                                if(fen==60)
                                                        fen=0;
                                               
                                       
                                        }
                                        if(s1num==3)
                                        {
                                                shi++;
                                                if(shi==24)
                                                        shi=0;
                                               
                                        }
                                }
                        }
                        if(sub==0)
                        {
                                delayms(10);
                                if(sub==0)
                                {
                                        while(!sub);
                                        if(s1num==1)
                                        {
                                       
                                                miao--;
                                                if(miao==-1)
                                                        miao=59;
                                               
                                        }
                                        if(s1num==2)
                                        {
                                                fen--;
                                                if(fen==-1)
                                                        fen=59;
                                       
                                        }
                                        if(s1num==3)
                                        {
                                                shi--;
                                                if(shi==-1)
                                                        shi=23;
                                               
                                        }
                                }
                        }
                }
       
             write_ds1302(DS1302_SECOND_WRITE,miao);
         write_ds1302(DS1302_MINUTE_WRITE,fen);
        write_ds1302(DS1302_HOUR_WRITE,shi);
}

出0入0汤圆

 楼主| 发表于 2012-11-12 00:03:13 | 显示全部楼层
这样写对吗?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-1 23:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表