打印

DS1302年寄存器问题!急!

[复制链接]
2143|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
英雷科电子|  楼主 | 2014-6-12 10:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近使用DS1302芯片,里面有个年寄存器,取值的范围是00-99,但是,我这边写入数据的时候,最大只能写到79。从内部读出来的数据也是同样,其他位都正常。
比如我现在把所有数据按照79年12月31日23时59分50秒设置。过10秒钟之后,时钟系统会自动进位,从内部读取出来的数据是00年01月01日,00时00分00秒。
求大神解!!!

相关帖子

沙发
weilaiheike| | 2014-6-12 14:02 | 只看该作者
驱动程序的问题吧,芯片很少出现个别位出问题的情况

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
英雷科电子 + 1 很给力!
板凳
英雷科电子|  楼主 | 2014-6-12 15:22 | 只看该作者
把程序贴出来给大家看看吧,希望大家能帮助下!!
硬件没有问题。用的是PIC16F690单片机。
//地址、数据发送子程序
void Write1302(unsigned char addr,unsigned char dat)
{
        unsigned char i,temp,temp_1;
        temp=dat/10;
        temp_1=dat%10;
        dat=temp*16+temp_1;                        //将十进制转换成ds1302的BCD内码,储存
        TRISB4=0;
        RB5=0;
        delay1302(2);                                        //CE引脚为低,数据传送
        RB6=0;
        delay1302(2);                                        //清空时钟总线
        RB5=1;
        delay1302(2);                                        //CE引脚为高,逻辑控制有效
        //发送地址
        for(i=8;i>0;i--)
        {
                RB6=0;
                delay1302(2);
                RB4=(bit)(addr&0x01);
                addr>>=1;
                delay1302(2);
                RB6=1;
                delay1302(2);
        }
        //发送数据
        for(i=8;i>0;i--)
        {
                RB6=0;
                delay1302(2);
                RB4=(bit)(dat&0x01);
                dat>>=1;
                delay1302(2);
                RB6=1;
                delay1302(2);
        }
        RB5=0;
        delay1302(2);
}


//数据读取子程序
unsigned char Read1302(unsigned char addr)
{
        unsigned char i,temp,dat1,dat2;
        RB5=0;       
        RB6=0;
        RB5=1;
        relay.allrel=0;
        TRISB4=0; // 设置数据口方向为输出
        //发送地址
        for(i=8;i>0;i--)
        {
                RB6=0;
                temp=addr;
                RB4=(bit)(temp&0x01);
                addr>>=1;
                RB6=1;
        }
        TRISB4=1; // 设置数据口方向为输入       
        //读取数据
        for(i=8;i>0;i--)
        {
                relay.state.relay_7=RB4;
                RB6=1;
                relay.allrel>>=1;
                RB6=0;
        }
        TRISB4=0; // 设置数据口方向为输出
        RB5=0;
        dat2=relay.allrel&0x0f;
        dat1=((relay.allrel>>4)&0x0f);                //数据转换,BCD码转换成十进制数据显示
        dat1=dat1*10+dat2;
        return(dat1);
}

使用特权

评论回复
地板
英雷科电子|  楼主 | 2014-6-16 10:35 | 只看该作者
这个问题,现在来给大家解释一下,经过几天的努力和同事共同思考,终于找到问题了,希望对大家有所帮助!
首先,是逻辑的问题。在读取的时候,每次从高位向低位移动一位,当第八位被赋值的时候,后面是不需要移位的,问题就出现在这个地方,我们的程序里面出现了第八位移位,所以,最高位始终为0;所以程序应该被改为:
  //读取数据
        for(i=8;i>0;i--)
        {
                relay.state.relay_7=RB4;
                RB6=1;
                if(i!=1)relay.allrel>>=1;
                RB6=0;
        }
这样的话,就可以避免出现最高位赋值以后,再被移位的情况。其他的移位也都可以修改下,因为其他的寄存器没有涉及到最高位的值,所以,没有加”if(i!=1)”这条指令,不影响程序的读取,和数据的处理。其他的移位指令之前也加上这个条件语句最佳!
还有就是一个时序的问题。
读取控制字发过去以后,紧接着要把信号拉低,然后再置高。置高以后,第一个下降沿,ds1302芯片向单片机发送数据。一定要注意时序的问题!!!!
下面是我改完以后的程序,给大家做个参考!!
unsigned char Read1302(unsigned char addr)
{
        unsigned char i,temp,dat1,dat2;
        RB5=0;       
        RB6=0;
        RB5=1;
        relay.allrel=0;
        TRISB4=0; // 设置数据口方向为输出
        //发送地址
        for(i=8;i>0;i--)
        {
                RB6=0;
                temp=addr;
                RB4=(bit)(temp&0x01);
                if(i!=1)addr>>=1;
                RB6=1;
        }
        RB6=0;
        TRISB4=1; // 设置数据口方向为输入       
        //读取数据
        for(i=8;i>0;i--)
        {
                relay.state.relay_7=RB4;
                RB6=1;
                asm("nop");
                asm("nop");
                if(i!=1)relay.allrel>>=1;
                RB6=0;
        }
        TRISB4=0; // 设置数据口方向为输出
        RB5=0;
        dat2=relay.allrel&0x0f;
        dat1=((relay.allrel>>4)&0x0f);                //数据转换,BCD码转换成十进制数据显示
        dat1=dat1*10+dat2;
        return(dat1);
}

使用特权

评论回复
5
ningling_21| | 2014-6-16 12:46 | 只看该作者
还是程序出问题了...

使用特权

评论回复
6
youluo235| | 2014-6-16 14:34 | 只看该作者
读的时候在循环里面当然要先移位在读取。这就保证最后一位是读出来的数据。就相当于只移了7为而不是8位。

使用特权

评论回复
7
英雷科电子|  楼主 | 2014-6-16 16:53 | 只看该作者
youluo235 发表于 2014-6-16 14:34
读的时候在循环里面当然要先移位在读取。这就保证最后一位是读出来的数据。就相当于只移了7为而不是8位。 ...

是的,就是因为这个移位出问题了,所以导致数据出错!

使用特权

评论回复
8
英雷科电子|  楼主 | 2014-6-16 16:54 | 只看该作者
ningling_21 发表于 2014-6-16 12:46
还是程序出问题了...

以后应该多多注意!多谢提醒!

使用特权

评论回复
9
smaple| | 2016-12-21 16:43 | 只看该作者
英雷科电子 发表于 2014-6-16 10:35
这个问题,现在来给大家解释一下,经过几天的努力和同事共同思考,终于找到问题了,希望对大家有所帮助!
...

你好 我的程序也出现了类似的问题 请问能帮忙解决下吗
void write_byte(uchar dt)          //DS1302有关子函数  写一个字节8byte
           {
                           ACC=dt;CE=1;
                            for(a=8;a>0;a--)
                                 {
                                   IO=ACC0;
                                   SCLK=0;
                                   SCLK=1;
                                   ACC=ACC>>1;
                          }
                }
          uchar read_byte()           //读一个字节
            {
                  CE=1;
                for(a=8;a>0;a--)
                                  
                 {
                    ACC7==IO;
                        SCLK=1;
                    SCLK=0;
                        ACC=ACC>>1;
                        }
                        return(ACC);
                   }
                void ds1302write(uchar add,uchar dat)//向1302芯片写数据,指定写入地址,数据
                   {
                           uchar dd1;        
                          
                           //        dd1=(dat/10)*16+(dat%10);
                            
                                 
                                   CE=0;
                                   SCLK=0;
                                   CE=1;
                                   write_byte(add);
                            write_byte(dat);
                                   SCLK=1;
                                   CE=0;

                   }
                uchar ds1302read(uchar add)//从1302读数据函数,指定读取数据来源地址
                  {
                          uchar temp;
                        CE=0;
                        SCLK=0;
                        CE=1;
                        write_byte(add);
                        temp=read_byte();
                        SCLK=1;
                        CE=0;
                        return(temp);
                  }
                  uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制
                   {
                            uchar Decimal;
                         Decimal=bcd>>4; //bcd码右移四位高四位(十位)—转到——低四位(个位)
                         return(Decimal=Decimal*10+(bcd&=0x0F));//bcd=bcd&0x0f保留bcd低四位其他位清零
                   }
  void ds1302init()
   {
     uchar n;
         
         ds1302write(0x8E,0x00);
         for(n=0;n<7;n++)
            {
                ds1302write(WRITE_RTC_ADDR[n],TIME1[n]);
            }
                ds1302write(0x8E,0x80);
         }
        void ds1302readtime()
    {
         uchar n;
         for (n=0;n<7;n++)
           {
              TIME[n]=ds1302read(READ_RTC_ADDR[n]);
           }
         }

使用特权

评论回复
10
smaple| | 2016-12-21 17:05 | 只看该作者
youluo235 发表于 2014-6-16 14:34
读的时候在循环里面当然要先移位在读取。这就保证最后一位是读出来的数据。就相当于只移了7为而不是8位。 ...

你好 出现相同问题看了好久 请问能帮忙吗看下程序不

使用特权

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

本版积分规则

1

主题

10

帖子

1

粉丝