xtl2012 发表于 2012-9-8 13:14:29

求教 关于DS1302时钟芯片时序程序(有尝的求救)

这几天在弄个1602液晶显示时钟,用DS1302时钟芯片提供时间;但在中途出现了点小问题,
对着DS1302时序图写完这部分程序,想试试程序是否对,就用一个8个LED灯P0接收DS1302的数据,
如果8个LED灯发生变化说明没有对着时序图写的这部分驱动没问题,但发现并不这么理想,8个LED全亮(LED共阳),
没有发生变化,说明DS1302驱动程序那部分有问题;可调试了很久也不知道哪里出错了.望好心人大神们帮助下。
(很想知道哪里错了,有尝的求救,如果有意愿帮助指导下的,可以加我QQ1097957773,,谢谢)

以下是时序图:


以下是DS1302驱动部分程序:
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char

void DS1302_COMMAND_WRITE(uchar adr);
void DS1302_DATA_WRITE(uchar date);
void switch_10_16(uchar transition);
void delay(uint z);
void delaynop();

uchar receive_io,shift_date;

void delaynop()
{
        _nop_();
        _nop_();       
        _nop_();
        _nop_();
}

/***************************/
/*                                  */   
/*        DS1302时钟位定义   */
/*                               */
/***************************/
sbit RST=P2^0;                          
sbit io=P2^2;                          
sbit SCLK=P2^1;                          




/***************************************/
/*                                     */
/*                延时函数                            */
/*                                     */
/***************************************/
void delay(uint z)
{
        uint x,y;

        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}



/***************************************/
/*                                     */
/*        DS1302时钟写保护函数                            */
/*                                     */
/***************************************/
void WRITE_PROTECT(uchar protect)
{
        DS1302_COMMAND_WRITE(0x8E);//DS1302 CONTROL地址位
        DS1302_DATA_WRITE(protect);//DS1302 CONTROL数据位

}



/*****************************************/
/*                                        */
/*        DS1302时钟地址写操作函数             */
/*                                        */
/*****************************************/
void DS1302_COMMAND_WRITE(uchar adr)   
{                                                                               
    uchar i;                                                       
        RST=0;                                                                                                                               
        SCLK=0;
        RST=1;        //高电平开始
        delaynop();                                                               
        for(i=0;i<8;i++)                                       
        {                                                                       
                adr=adr>>1;                                               
                io=adr&0x80;//1位送入DS1302芯片中
                SCLK=1;//高脉冲送出数据
                delaynop();                                                                                                      
                SCLK=0;                                                       
                delaynop();                                               
        }                                                                       
                                                                               
}        //地址写完 SCLK为低电平                                                               



/***************************************/
/*                                        */
/*        DS1302时钟数据写操作函数          */
/*                                     */
/***************************************/
void DS1302_DATA_WRITE(uchar date)          
{                                                                          
        uchar i;
        switch_10_16(date);        //数值转换                                           
        for(i=0;i<8;i++)                                  
        {       
                io=shift_date&0x01;        //低位与运算判断0和1                                                          
                shift_date=shift_date>>1;//转换后的数据进行移位传输                                                             
                SCLK=1;//高脉冲送出数据                                                  
                delaynop();                                                  
                SCLK=0;          
                delaynop();                                                  
        }
        SCLK=1;//写完后按时序图SCLK先置高
        RST=0;//RST在置低
}                                                                          



/***************************************/
/*                                        */
/*        DS1302时钟数据读操作函数          */
/*                                     */
/***************************************/
void DS1302_READ(uchar adre)
{
        uchar i;
        receive_io=0;
        DS1302_COMMAND_WRITE(adre);//写完地址后SCLK为低电平,需要一个高电平过度在开始读操作
        SCLK=1;
        delaynop();
        for(i=0;i<8;i++)
        {
                SCLK=0;//低脉冲读走数据
                delaynop();       
                receive_io=receive_io>>1;
                if(io==1)
                        {
                                receive_io=receive_io|0x80;//高位补1
                        }
                else
                        {
                                receive_io=receive_io|0x00;//高位补0
                        }
               
                       
        }
        SCLK=1;
        delaynop();
        RST=0;
}



/*****************************************/
/*                                        */
/*        DS1302时钟总体写操作函数             */
/*                                        */
/*****************************************/
void DS1302_WRITE(uchar adress,uchar dat)
{                                                                                  
   DS1302_COMMAND_WRITE(adress);                  
   DS1302_DATA_WRITE(dat);                                  
}                                                                                  



/***************************************/
/*                                     */
/*                发送_数值转换函数          */
/*                                     */
/***************************************/
void switch_10_16(uchar transition)
{
        uchar ge,shi;
        shi=transition/10;
        ge=transition%10;
        shift_date=shi*16+ge;
}


void main()
{
       WRITE_PROTECT(0x00);//去除写保护
       delaynop();       
       DS1302_WRITE(0x80,13);
       delaynop();       
       while(1)
       {
              DS1302_READ(0x81);
               delaynop();       
               P0=receive_io;       
       }
}


horalxi 发表于 2012-9-8 13:50:55

玩DS1302最难的地方在于读完后紧接着写,
建议你再好好研究一下这段,
实在弄不出来,我给你一份调试通过的。

xtl2012 发表于 2012-9-8 17:18:57

horalxi 发表于 2012-9-8 13:50 static/image/common/back.gif
玩DS1302最难的地方在于读完后紧接着写,
建议你再好好研究一下这段,
实在弄不出来,我给你一份调试通过的 ...

我已经调试了1天多了,从头到尾都看了,可也弄不出来,你能留个QQ吗?

physics 发表于 2012-9-8 17:27:32

xtl2012 发表于 2012-9-8 17:36:15

physics 发表于 2012-9-8 17:27 static/image/common/back.gif
网上很多,找找看吧

你帮我看看我程序 时序那里有错好吗?网上的都看过.

millwood0 发表于 2012-9-8 22:27:12

很想知道哪里错了

basically, very poor structuring of your code. you should try to use 1 routine to send a byte to the chip and another routine to read a byte from the chip, and build the rest of the routines from that.

try this one#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char

void DS1302_COMMAND_WRITE(uchar adr);
void DS1302_DATA_WRITE(uchar date);
void switch_10_16(uchar transition);
void delay(uint z);
void delaynop();

uchar receive_io,shift_date;

void delaynop()
{
      _nop_();
      _nop_();      
      _nop_();
      _nop_();
}

/***************************/
/*                                    */   
/*      DS1302?????   */
/*                               */
/***************************/
sbit RST=P2^0;                           
sbit io=P2^2;                           
sbit SCLK=P2^1;                           




/***************************************/
/*                                       */
/*                ????                            */
/*                                       */
/***************************************/
void delay(uint z)
{
      uint x,y;

      for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}

//reset the bus
void DS1302_INIT(void) {
      RST=0;                                                                                                                                 
      SCLK=0;
}




/*****************************************/
/*                                          */
/*      DS1302?????????               */
/*                                          */
/*****************************************/
void DS1302_BYTE_WRITE(uchar adr)   
{                                                                              
    uchar i;                                                         
      //RST=0;                                                                                                                                 
      //SCLK=0;
      //RST=1;      //?????
      //delaynop();                                                               
      for(i=0;i<8;i++)                                       
      {                                                                        
                                SCLK = 0;                                        //reset sclk to idle
                //adr=adr>>1;                                                
                io=(adr&0x01)?1:0;//1???DS1302???
                //delaynop();                                                                                                         
                SCLK=1;//???????
                                adr = adr >> 1;
                //SCLK=0;                                                         
                //delaynop();                                                
      }                                                                        
                                                                                 
}      //???? SCLK????                                                               

uchar DS1302_BYTE_READ(void)   
{
        uchar adr=0;                                        //temp variable                                                                              
    uchar i;                                                         
      //RST=0;                                                                                                                                 
      //SCLK=0;
      //RST=1;      //?????
      //delaynop();                                                               
                io = 1;                                                //wait to read io
      for(i=0;i<8;i++)                                       
      {                                                                        
                                SCLK = 0;                                        //reset sclk to idle
                adr=adr>>1;                                                
                //delaynop();                                                                                                         
                                adr |= (io)? 0x80: 0x00;        //=(adr&0x01)?1:0;//1???DS1302???
                SCLK=1;//???????
                //SCLK=0;                                                         
                //delaynop();                                                
      }                                                                        
        return adr;                                                //return the value
}      //???? SCLK????
                                                            

/***************************************/
/*                                       */
/*      DS1302???????                            */
/*                                       */
/***************************************/
void xWRITE_PROTECT(uchar protect)
{
      DS1302_BYTE_WRITE(0x8E);//DS1302 CONTROL???
      DS1302_BYTE_WRITE(protect);//DS1302 CONTROL???

}



/***************************************/
/*                                          */
/*      DS1302?????????            */
/*                                       */
/***************************************/
void xDS1302_DATA_WRITE(uchar date)         
{                                                                           
      uchar i;
      switch_10_16(date);      //????                                          
      for(i=0;i<8;i++)                                 
      {      
                io=shift_date&0x01;      //???????0?1                                                         
                shift_date=shift_date>>1;//????????????                                                            
                SCLK=1;//???????                                                   
                delaynop();                                                   
                SCLK=0;         
                delaynop();                                                   
      }
      SCLK=1;//???????SCLK???
      RST=0;//RST???
}                                                                           


/***************************************/
/*                                          */
/*      DS1302?????????            */
/*                                       */
/***************************************/
uchar DS1302_READ(uchar adre)
{
      uchar i;
      //receive_io=0;
      //reset the bus
                RST=0;                                                                                                                                 
      SCLK=0;
      RST=1;      //?????
      DS1302_BYTE_WRITE(adre);//?????SCLK????,???????????????
      i=DS1302_BYTE_READ();
                //return the bus to idle
                SCLK=0;
                RST=0;
                return i;                                //return the value
/*                SCLK=1;
      delaynop();
      for(i=0;i<8;i++)
      {
                SCLK=0;//???????
                delaynop();      
                receive_io=receive_io>>1;
                if(io==1)
                        {
                              receive_io=receive_io|0x80;//???1
                        }
                else
                        {
                              receive_io=receive_io|0x00;//???0
                        }
               
                        
      }
      SCLK=1;
      delaynop();
      RST=0;
*/

}



/*****************************************/
/*                                          */
/*      DS1302?????????               */
/*                                          */
/*****************************************/
void DS1302_WRITE(uchar adress,uchar dat)
{                                                                                 
      //reset the bus
                RST=0;                                                                                                                                 
      SCLK=0;
      RST=1;      //?????
   DS1302_BYTE_WRITE(adress);                  
   DS1302_BYTE_WRITE(dat);                                 
                //return the bus to idle
                SCLK=0;
                RST=0;
}                                                                                 



/***************************************/
/*                                       */
/*                ??_??????            */
/*                                       */
/***************************************/
uchar dec2bcd(uchar dec)
{
/*      uchar ge,shi;
      shi=transition/10;
      ge=transition%10;
      shift_date=shi*16+ge;
*/
        return ((dec / 10) << 4) | (dec % 10);
}


void main()
{
        DS1302_INIT();                                //reset the bus
         //WRITE_PROTECT(0x00);//?????
               DS1302_WRITE(0x8e, 0x00);
         delaynop();      
         DS1302_WRITE(0x80,13);
         delaynop();      
         while(1)
         {
               receive_io= DS1302_READ(0x81);
               delaynop();      
               P0=receive_io;      
         }
}
it is largely based on yours, but not fully cleaned up.

xtl2012 发表于 2012-9-8 23:28:54

millwood0 发表于 2012-9-8 22:27 static/image/common/back.gif
basically, very poor structuring of your code. you should try to use 1 routine to send a byte to t ...

I try your program that you give me ,Althoughprogram   can't work normally, but thank you all the same.

zyyn123 发表于 2012-9-8 23:45:42

/*****************************************/
/*                                          */
/*      DS1302时钟地址写操作函数               */
/*                                          */
/*****************************************/
void DS1302_COMMAND_WRITE(uchar adr)   
{                                                                              
    uchar i;                                                         
      RST=0;                                                                                                                                 
      SCLK=0;
      RST=1;      //高电平开始
      delaynop();                                                               
      for(i=0;i<8;i++)                                       
      {                                                                        
                adr=adr>>1;                                           //这句应该往下面移      
                io=adr&0x80;//1位送入DS1302芯片中       //这句改为 io=adr&0x01;               
         SCLK=1;//高脉冲送出数据
         delaynop();                                                                                                         
                SCLK=0;                                                         
                delaynop();                                                
      }                                                                        
                                                                                 
}      //地址写完 SCLK为低电平         

millwood0 发表于 2012-9-9 00:26:41

here is the code I posted, outputting receive_io on p3.



the rtc was reset to 13 (0x13 in bcd format) initially.

so from 1s - 2s, the second should be 13 (0x14 in bcd format). that corresponds to P3.4 = 1, P3.2 = 1, and P3.x cleared -> P3 = 0x14, as you can see on the chart.

from 6 - 7s, the second should be 19 (0x19 in bcd format). P3 reads 0x19, correctly.

from 7s - 8s, the second will advance to 20, which causes the bcd reading to go from 0x19 to 0x20. You can see that there.

If the code I posted doesn't work on your hardware, you have other problems.

horalxi 发表于 2012-9-9 12:11:35

xtl2012 发表于 2012-9-8 17:18 static/image/common/back.gif
我已经调试了1天多了,从头到尾都看了,可也弄不出来,你能留个QQ吗?

别着急,以前我调试的时候,弄了一个星期,后来发现了问题点,茅塞顿开,以后再调试DS1302就如鱼得水了。
qq:157185173

xtl2012 发表于 2012-9-9 12:41:17

zyyn123 发表于 2012-9-8 23:45 static/image/common/back.gif
/*****************************************/
/*                                          */
/*      ...

嗯,发现了.谢谢你!

xtl2012 发表于 2012-9-9 12:41:46

DS1302驱动弄好了.花了两天时间调试,谢谢热心的网友们!谢谢!!!{:smile:}

yihui184 发表于 2012-11-7 23:41:39

horalxi 发表于 2012-9-9 12:11 static/image/common/back.gif
别着急,以前我调试的时候,弄了一个星期,后来发现了问题点,茅塞顿开,以后再调试DS1302就如鱼得水了。 ...

大侠,你好,我现在DS1302出现一个问题,就是大多情况下,我读出DS1302大多数次都能读出正确值,但是偶尔就会读出错误的一次日期值,我在读DS1302都有禁止中断。我用了纽扣电池,设置了下寄存器!也起作用了,但是就是偶尔会给我读出一个错误的日期值,请问,这种问题是什么情况哇?
页: [1]
查看完整版本: 求教 关于DS1302时钟芯片时序程序(有尝的求救)