打印

请教关于DS1302时钟程序设计的问题

[复制链接]
3205|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
单片小白菜|  楼主 | 2009-7-13 15:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我正在参加一个从实践中学会单片机的活动,要求用51单片机设计一个DS1302时钟程序。

这是活动的地址和详细的要求 http://bbs.cepark.com/thread-5032-1-1.html。

我在设计过程中遇到无法读出DS1302内部数据问题,读出来的数据是错误的.

下面我把读写程序发出来,大家帮我看看是哪地方出了问题...是不是时序或别的什么方面...

希望高手进行指导。呵呵,只有从实践中才能学会单片机,这也是我第一次认真做这类开发,对回帖的人先谢过!

void Write_DS_Byte(uint8 Command,uint8 Write_Data)
{
    uint8 i=0;
    DS_CE=0;
    DS_IO=0;
    DS_SCK=0;                                           //初始化各端口;
    for(i=0;i<8;i++)                                     //写入8位命令;
        {
            DS_CE=1;
            DS_IO=Command&0x01;                   //并行数据转为串行;
            DS_SCK=0;
            _nop_();
            DS_SCK=1;
            Command>>=1;                               //送下一位串行数据;
        }
    for(i=0;i<8;i++)                                    //写入8位数据;
        {
            DS_CE=1;
            DS_IO=Write_Data&0x01;                 //并行数据转为串行;
            DS_SCK=0;
            _nop_();
            DS_SCK=1;
            Write_Data>>=1;                          //送下一位串行数据;
        }    
    DS_CE=0;                                           //禁止传输;
}

uint8 Read_DS_Byte(uint8 Command)
{
    uint8 Value=0;
    uint8 i=0;
    DS_CE=0;
    DS_IO=0;
    DS_SCK=0;
    for(i=0;i<8;i++)                                       //写命令进DS1302内部;
        {
            DS_CE=1;
            DS_IO=Command&0x01;                      //送8位数据;
            DS_SCK=0;
            _nop_();
            DS_SCK=1;
            Command>>=1;                             //数据移位;
        }
    for(i=0;i<8;i++)                                      //读取DS1302返回的数据;
        {
            DS_SCK=1;
            DS_SCK=0;
            if(DS_IO!=0)                                  //把串行数据转为并行;
                {
                    Value|=0x01<<i;            //移位 ;
                }
            //Value>>=1;
        }
    DS_CE=0;
    return (Value);                                       //返回读取数据;
}


相关帖子

沙发
gongxd126com| | 2009-7-13 17:30 | 只看该作者

aa

#include "AT89X52.H"
#include "SysFunction.h"

#define uchar unsigned char
sbit T_CLK=P1^4;
sbit T_IO=P1^5;
sbit T_RST=P1^6;

sbit  ACC0 = ACC^0;
sbit  ACC7 = ACC^7;
   /******************************************************************** 
 说    明:从DS1302读取1Byte数据 (内部函数)
***********************************************************************/
uchar RTInputByte(void) 

    uchar i;
    for(i=8; i>0; i--)
    {

        ACC = ACC >>1;         /*相当于汇编中的 RRC */
        ACC7 = T_IO;
        T_CLK = 1;
        T_CLK = 0;

    } 
    return(ACC); 

}
/******************************************************************** 
 说    明: 往DS1302写入1Byte数据 (内部函数)
***********************************************************************/
void RTOutputByte(uchar d) 

    uchar i;
    ACC = d;
    for(i=8; i>0; i--)    
   {
      T_IO = ACC0;
      T_CLK = 1;
      T_CLK = 0;
      ACC = ACC >> 1; 
   }
   
}
/******************************************************************** 

 函 数 名:W1302()
 功    能:往DS1302写入数据
 说    明:先写地址,后写命令/数据 (内部函数)
 调    用:RTInputByte() , RTOutputByte()
 入口参数:ucAddr: DS1302地址, ucData: 要写的数据
***********************************************************************/
void W1302(uchar ucAddr, uchar ucDa)
{
    T_RST = 0;
    sysnop();sysnop(); sysnop(); 
    T_CLK = 0;
     sysnop(); sysnop();sysnop();
    T_RST = 1;
     sysnop(); sysnop();sysnop();
    RTOutputByte(ucAddr);       /* 地址,命令 */
    RTOutputByte(ucDa);       /* 写1Byte数据*/
    T_RST = 0;

/******************************************************************** 

 函 数 名:R1302()
 功    能:读取DS1302某地址的数据
 说    明:先写地址,后读命令/数据 (内部函数)
 调    用:RTInputByte() , RTOutputByte()
 入口参数:ucAddr: DS1302地址
***********************************************************************/
uchar R1302(uchar ucAddr)
{
    T_RST = 0;
      sysnop(); sysnop();sysnop();
    T_CLK = 0;
      sysnop(); sysnop();sysnop();
    T_RST = 1;
       sysnop(); sysnop();sysnop();
    RTOutputByte(ucAddr);             /* 地址,命令 */
    ucAddr = RTInputByte();         /* 读1Byte数据 */

    T_CLK = 0;
    T_RST = 0;
    return(ucAddr);
}
/******************************************************************** 

 函 数 名:BurstW1302T()
 功    能:往DS1302写入时钟数据(多字节方式)
 说    明:先写地址,后写命令/数据
 调    用:RTInputByte() 
 入口参数:pWClock: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年 控制
                            8Byte (BCD码)1B 1B 1B 1B 1B  1B  1B 1B 
***********************************************************************/
/*
void BurstW1302T(uchar *pWClock)
{
    uchar i;
    W1302(0x8e,0x00);         // 控制命令,WP=0,写操作? 
    T_RST = 0;
    T_CLK = 0;
    T_RST = 1;
    RTOutputByte(0xbe);        // 0xbe:时钟多字节写命令 
    for (i = 8; i>0; i--)     //8Byte = 7Byte 时钟数据 + 1Byte 控制 
    {
        RTOutputByte(*pWClock); // 写1Byte数据 
        pWClock++;
    }
    T_RST = 0;

*/
/******************************************************************** 
 功    能:读取DS1302时钟数据
 说    明:先写地址/命令,后读数据(时钟多字节方式)
 调    用:RTInputByte() , RTOutputByte()
 入口参数:pRClock: 读取时钟数据地址 格式为: 秒 分 时 日 月 星期 年
                               6Byte (BCD码)1B 1B 1B 1B 1B  1B  1B 
***********************************************************************/
/*
void readtimedate(uchar *pRClock)
{
    uchar i;
    T_RST = 0;
           sysnop(); sysnop();sysnop();
    T_CLK = 0;
           sysnop(); sysnop();sysnop();

    T_RST = 1;
             sysnop(); sysnop();sysnop();

    RTOutputByte(0xbf);             // 0xbf:时钟多字节读命令 
    for (i=6; i>0; i--) 
    {
       *pRClock = RTInputByte();   // 读1Byte数据 
       pRClock++;
    }
    i=RTInputByte();
    pRClock++;
    *pRClock = RTInputByte();

    T_RST = 0;
}
*/

 //读时分秒
void readtime(uchar *timebuff)
{
timebuff[0]= R1302(0x85);
timebuff[1]= R1302(0x83);
timebuff[2]= R1302(0x81);
}

//读年月日
void readdate(uchar *datebuff)
{
datebuff[0]= R1302(0x8d);
datebuff[1]= R1302(0x89);
datebuff[2]= R1302(0x87);
}


//写时分秒
void settime(uchar *timebuff)   
{
W1302(0x8e,0);
W1302(0x84,timebuff[0]);
W1302(0x82,timebuff[1]);
timebuff[2]&=0x7f;
W1302(0x80,timebuff[2]);  //启动时钟
W1302(0x8e,0x80);
}


//写年月日
void setdate(uchar *datebuff)  
{
W1302(0x8e,0);
W1302(0x8c,datebuff[0]);
W1302(0x88,datebuff[1]);
W1302(0x86,datebuff[2]);
W1302(0x8e,0);
W1302(0x8e,0x80);
//yy=yy&0x7f;
//W1302(0x80,yy); //启动时钟

}

/*写年月日
void setdate(uchar yy,uchar mm,uchar dd)  
{

W1302(0x8c,yy);
W1302(0x88,mm);
W1302(0x86,dd);

yy=yy&0x7f;
W1302(0x80,yy); //启动时钟

}
//写时分秒
void settime(uchar hh,uchar mm,uchar ss)   
{

W1302(0x84,hh);
W1302(0x82,mm);
ss=ss&0x7f;
W1302(0x80,ss);  //启动时钟

}


*/
    //1302 初始化
void init_ds1302()
{
       unsigned char x;
       W1302(0x8e,0);
       W1302(0x90,0xa6);
       x=R1302(0x81);
       if((x & 0x80)!=0)
       W1302(0x80,0); 
       W1302(0x8e,0x80);     
}

//读取指定地址RAM 
unsigned char byteget(unsigned char dsaddr)
{
 W1302(0x8e,0);
 dsaddr=dsaddr<<1;
 dsaddr|=0xc1;
 W1302(0x8e,0x80);
 return R1302(dsaddr);
}
//写指定地址RAM 
void byteset(unsigned char dsaddr,unsigned char dadata)
{
 W1302(0x8e,0);
 dsaddr=dsaddr<<1;
 dsaddr|=0xc0;
 W1302(dsaddr,dadata);
 W1302(0x8e,0x80);
}

使用特权

评论回复
板凳
kidcao1987| | 2009-7-13 20:33 | 只看该作者

2楼强大

使用特权

评论回复
地板
460418411| | 2009-7-31 14:13 | 只看该作者

解决问题之道?

现在的技术论坛大把,但真正起到交流并解决问题的不多。。。原因很多。。。
说下我的感受,像我之前用DS1302时一开始也是有问题,这次我没有将问题发到网上求助,而是回头看datasheet,并到Dallas的网站下载DS1302的代码,问题很快解决。。。。

使用特权

评论回复
5
john_light| | 2009-8-2 00:02 | 只看该作者
用到ACC的比较早的公开版本好象是 广州老赵 的程序

我 反正我是不敢这样用

使用特权

评论回复
6
bear15888| | 2009-8-2 09:21 | 只看该作者
我马上也要用这芯片了,先瞧瞧!

使用特权

评论回复
7
踢球老越位| | 2009-8-2 22:16 | 只看该作者
用c语言了为何还用ACC?不怕冲突啊?夜路走多了要小心......

使用特权

评论回复
8
new1988| | 2009-8-5 21:12 | 只看该作者
怎么大家现在还用DS1302这块过时的芯片啊,时间不准不说,做到实物上很多麻烦,我曾经用这块芯片的时候在仿真的时候蛮好的,但是做到实物上它的时间就是不走,就这个问题折腾了一个多礼拜,把学校的老师全部问遍都没问出个结果,最后由于不小心在芯片的数据口和时钟口接了两根悬空的线它尽然就走了。所以在做成实物的时候一定要在数据口和时钟口接上上拉电阻。

使用特权

评论回复
9
ningling_21| | 2009-8-5 22:14 | 只看该作者
网上的成功的例程很多,下载个改下就能用了,何必浪费时间......

使用特权

评论回复
10
kylezhou| | 2009-8-5 23:13 | 只看该作者
1302本身不是问题,时间准基本上电容和晶体的问题。如果时间没走,百分之八十是没有正确的初始化,百分之十九是电容值不对,并且电容值的大小会对时间的准确性产生很大的影响,你在学校做的板,很可能用的是普通电容,而通常此处应用精度比较高的电容,这个电容超过8PF,时间就开始慢了。理论上讲,你没有正确初始化的话不但时间不走, 晶体都不会起振的。或者你可能买了到山寨货!:D

使用特权

评论回复
11
new1988| | 2009-8-6 10:19 | 只看该作者
我肯定初始化了啊,但是晶振根本就没接电容,一样的能走,而且走个一两个月时间还是蛮准的啊。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

13

帖子

1

粉丝