微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > ds1302 芯片掉电数据归零问题 ?已经安装备用电池!

ds1302 芯片掉电数据归零问题 ?已经安装备用电池!

时间:10-02 整理:3721RD 点击:

ds1302 芯片,时间运行的很准,走时正常,安装备用电池也能正常工作, 当电源断电后,隔几分钟再给电 时间也正常运行!
但是发现设备一直工作 不一定哪一天(也许3天后,也许半个月后,可能跟停电有关,停电时间长短有关系)
举个例子:时间显示本应该18:00:00 变成 01:00:00  我怀疑可能什么因素导致DS1302 归位或者晶振停振了!
在设备上接有一个TT电机 通过 104电容和22uf的电解电容抗干扰 还串联了一个47亨的电感, DS1302电源供电也并联一个10uf的电解电容!

程序如下:

#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
void delay_main(uint z);
/*******************************************************************************
以下是对液晶模块的操作程序
*******************************************************************************/
unsigned char time;           //忙碌标志位,,将BF位定义为P0.7引脚
sbit LCD_RS = P1^0;            
sbit LCD_RW = P1^1;
sbit LCD_EN = P1^2;
sbit  BEEP = P1^3;
sbit  DENG = P1^4;
sbit  DENGSHI=P3^7;
//sbit lcde=P2^7;
//sbit rs=P2^6;
//sbit rw=P2^5;
sbit  K1 = P3^0;
sbit  K2 = P3^1;
sbit  K3 = P3^2;
sbit  K4 = P3^3;
sbit  B1 = P2^0;
sbit  B2 = P2^1;
sbit  B3 = P2^2;
sbit  B4 = P2^4;
sbit  BEIDENG=P2^3;


sbit reset = P1^7;
sbit sclk  = P1^5;
sbit io    = P1^6;
//sbit SCK=P3^6;        //时钟        
//sbit SDA=P3^4;        //数据        
//sbit RST=P3^5;// DS1302复位

bit flag=1,hour=0,min=0,sec=0;
bit year=0,month=0,day=0,week=0;
bit alarm_flag=0;
uchar  timecount=0,count=0;
uchar str1[]="  -  -   Week:  ";
uchar str2[]="               ";
uchar init [] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00};  //
uchar init1[] ={0x00,0x00};
uchar init2[] ={0x00,0x59,0x23,0x01,0x05,0x01,0x06}; //
               //秒, 分, 时, 日, 月,星期,年
uchar bj_time[] ={0x00,0x57,0x22};
                 //秒, 分, 时
uchar code  mytab[8] = {0x00,0x00,0x0E,0x04,0x0A,0xFF,0x00,0x00};//小灯        //显示右下角开灯图标
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
void  Set_W1302(uchar addr);
void  Set_Flash(uchar row,uchar col);
void  Set_place(uchar row,uchar col);
void  Play_nowtime();
void  key_set(uchar num,uchar row,uchar col );
void  alarm_time();
void  Play_alarmtime();
void  Time_compare();
/******************************************************************/
/******************************************************************/
void delay1(int ms)
{
unsigned char y;
  while(ms--)
{
  for(y = 0; y<250; y++)
  {
   _nop_();
   _nop_();
   _nop_();
   _nop_();
  }
}
}
/******************************************************************/
/*                                                                */
/*检查LCD忙状态                                                   */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。     */
/*                                                                */
/******************************************************************/
bit lcd_busy()
{                          
    bit result;
    LCD_RS = 0;
    LCD_RW = 1;
    LCD_EN = 1;
    delayNOP();
    result = (bit)(P0&0x80);
    LCD_EN = 0;
    return(result);
}
/*********************************************************/
/*                                                       */
/*写指令数据到LCD                                        */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。                   */
/*                                                       */
/*********************************************************/
void lcd_wcmd(uchar cmd)
{                          
   while(lcd_busy());
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 0;
    _nop_();
    _nop_();
    P0 = cmd;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;  
}
/*********************************************************/
/*                                                       */
/*写显示数据到LCD                                        */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。                     */
/*                                                       */
/*********************************************************/
void lcd_wdat(uchar dat)
{                          
   while(lcd_busy());
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_EN = 0;
    P0 = dat;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;
}
/*********************************************************/
/*                                                       */
/*  LCD初始化设定                                        */
/*                                                       */
/*********************************************************/
void init_lcd()
{
    delay1(15);   
    lcd_wcmd(0x01);      //清除LCD的显示内容
    lcd_wcmd(0x38);      //16*2显示,5*7点阵,8位数据
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);
    lcd_wcmd(0x0c);      //显示开,关光标
    delay1(5);
    lcd_wcmd(0x06);      //移动光标
    delay1(5);
    lcd_wcmd(0x01);      //清除LCD的显示内容
    delay1(5);
}
/*********************************************************/
//
/*********************************************************/
void delay()
{
   uchar j;
   for(j=250;j>0;j--);
}
/*********************************************************/
/*                                                       */
/*  写字符串函数                                         */
/*                                                       */
/*********************************************************/
void write_str(uchar addr,uchar *p)
{
   uchar i=0;
   lcd_wcmd(addr);
   while(p!='\0')
   {
    lcd_wdat(p);
    i++;
   }
}
/*********************************************************/
/*                                                       */
/*  设定显示位置                                         */
/*                                                       */
/*********************************************************/
void write_position(uchar row,uchar col)
{
   uchar place;
   if(row==1)
   {
     place=0x80+col-1;
     lcd_wcmd(place);
   }
   else
   {
     place=0xc0+col-1;
     lcd_wcmd(place);
   }
}
/*********************************************************/
/*                                                       */
/*自定义字符写入CGRAM                                    */
/*                                                       */
/*********************************************************/
void  writetab()  
{  
    unsigned char i;
    lcd_wcmd(0x40);            //写CGRAM
    for (i = 0; i< 16; i++)      
    lcd_wdat(mytab);        
}
/**********************************************************/
//
/**********************************************************/
void write_byte(uchar inbyte)
{
   uchar i;
   for(i=0;i<8;i++)
   {
    sclk=0;             //写的时候低电平改变数据
    if(inbyte&0x01)
    io=1;
    else
    io=0;
    sclk=1;            //写的时候高电平,把数据写入ds1302
    _nop_();
    inbyte=inbyte>>1;
   }
}
/**********************************************************/
/**********************************************************/
uchar read_byte()    //sclk的下跳沿读数据
{
   uchar i,temp=0;
   io=1;                //设置为输入口
   for(i=0;i<7;i++)
   {
    sclk=0;
    if(io==1)
    temp=temp|0x80;
    else
    temp=temp&0x7f;
    sclk=1;             //产生下跳沿
    temp=temp>>1;
   }
   return (temp);
}
/**********************************************************/
// 往ds1302的某个地址写入数据
/**********************************************************/
void write_ds1302(uchar cmd,uchar indata)
{
   sclk=0;
   reset=1;
   write_byte(cmd);        
   write_byte(indata);
   sclk=0;
   reset=0;
}
/**********************************************************/
// 读ds1302某地址的的数据
/**********************************************************/
uchar read_ds1302(uchar addr)
{
   uchar backdata;
   sclk=0;
   reset=1;
   write_byte(addr);      //先写地址
   backdata=read_byte();  //然后读数据
   sclk=0;
   reset=0;
   return (backdata);
}
/**********************************************************/
// 设置初始时间
/**********************************************************/
void set_ds1302(uchar addr,uchar *p,uchar n) //写入n个数据
{
   write_ds1302(0x8e,0x00);          //写控制字,允许写操作
   for(;n>0;n--)
   {
   write_ds1302(addr,*p);
   p++;
   addr=addr+2;
   }
   write_ds1302(0x8e,0x80);          //写保护,不允许写
}
/**********************************************************/
// 读取当前时间
/**********************************************************/
void read_nowtime(uchar addr,uchar *p,uchar n)
{
  for(;n>0;n--)
  {
    *p=read_ds1302(addr);
    p++;
    addr=addr+2;
  }
}
/**********************************************************/
// 初始化DS1302
/**********************************************************/
void init_ds1302()
{
   reset=0;
   sclk=0;
   write_ds1302(0x80,0x00);
   write_ds1302(0x90,0xa8); //一个二极管+4K电阻充电
   write_ds1302(0x8e,0x80); //写保护控制字,禁止写
}
/**********************************************************/
/*                                                        */
/* 蜂鸣器响一声                                           */
/*                                                        */
/**********************************************************/

void beep()
  {
}
/*
********************************************************************************
** 函数名称 : delay(uint z)
** 函数功能 : 延时函数
********************************************************************************
*/
void delay_main(uint z)//-----------------主延时函数1毫秒
{ uint x,y; for(x=z;x>0;x--)
   for(y=100;y>0;y--);
  }

/**********************************************************/
/*                                                        */
/* :闪动函数                                          */
/*                                                        */
/**********************************************************/
void  flash()
{
   if(flag)
    {
      write_position(2,3);
      lcd_wdat(':');
      write_position(2,6);
      lcd_wdat(':');     
    }
    else
    {
      write_position(2,3);
      lcd_wdat(0x20);
      write_position(2,6);
      lcd_wdat(0x20);     
    }
}
/**********************************************************/
// 主函数
/**********************************************************/
void main()
{
   BEEP=1;
   DENG=1;
   BEIDENG=0;
   TMOD=0x01;
   TH0=0x4c;          //50ms定时
   TL0=0x00;
   EA=1;
   ET0=1;  
   TR0=1;
   init_lcd();                 //初始化LCD
   write_str(0x80,str1);       //液晶显示提示信息
   write_str(0xc0,str2);       //液晶显示提示信息
   init_ds1302();              //初始化ds1302
   writetab();               //自定义字符写入CGRAM
//   delay1(5);
//   write_position(2,16);
//   lcd_wdat(0x00);           //显示自定义字符小喇叭
   while(1)
   {
//---------------------------------------------------------
    if(B1==0&BEEP==1)  //手动喂食
        {  
                BEEP=0;
        //        BEIDENG=0;
                delay1(3000);
                BEEP=1;
        //        BEIDENG=1;
        
        }
   if(B2==0&DENG==1)  //手动开灯
   {DENG=0;BEIDENG=0;write_position(2,16); lcd_wdat(0x00);delay1(200);}
           
   if(B2==0&DENG==0)  //手动关灯
   {DENG=1;BEIDENG=0;write_position(2,16); lcd_wdat(0x20); delay1(200);}      
   kll:
   if(B3==0&BEIDENG==1)  //手动开背灯
   {BEIDENG=0;delay1(200);}
           
   if(B3==0&BEIDENG==0)  //手动关背灯
   {BEIDENG=1;delay1(200);}      
   klle:

        Play_nowtime();
        Time_compare();
   }
}
/**********************************************************/
// Time0中断函数
/**********************************************************/
void Time0(void) interrupt 1 using 0
{
  TH0=0x4c; //50ms定时
  TL0=0x00;
  timecount++;
  if(timecount>9)
   {
    timecount=0;   
    flag=~flag;            
   }  
}
/**********************************************************/
// 设定值写入DS1302
/**********************************************************/
void  Set_W1302(uchar addr)
{
   uchar  temp;
   write_ds1302(0x8e,0x00);
   temp=(init1[0]<<4)+init1[1];
   write_ds1302(addr,temp);
   write_ds1302(0x8e,0x80);
   beep();
}

/**********************************************************/
// 指定位置显示
/**********************************************************/
void  Set_place(uchar row,uchar col)
{
    write_position(row,col);
    lcd_wdat(init1[0]+0x30);
    write_position(row,col+1);
    lcd_wdat(init1[1]+0x30);
}
/**********************************************************/
// 显示当前时间
/**********************************************************/
void  Play_nowtime()
{
    read_nowtime(0x81,init,7);   //读出当前时间,读出7个字节
    write_position(2,1);
    lcd_wdat(((init[2]&0xf0)>>4)+0x30);
    write_position(2,2);
    lcd_wdat('0'+(init[2]&0x0f)); //读小时
   // write_position(2,3);
   // lcd_wdat(':');
    write_position(2,4);
    lcd_wdat('0'+((init[1]&0xf0)>>4));
    write_position(2,5);
    lcd_wdat('0'+(init[1]&0x0f)); //读分钟
//    write_position(2,6);
//    lcd_wdat(':');
    write_position(2,7);
    lcd_wdat('0'+((init[0]&0xf0)>>4));
    write_position(2,8);
    lcd_wdat('0'+(init[0]&0x0f)); //读秒
    write_position(1,1);
    lcd_wdat('0'+((init[6]&0xf0)>>4));
    write_position(1,2);
    lcd_wdat('0'+(init[6]&0x0f)); //读年
//    write_position(1,3);
//    lcd_wdat('/');
    write_position(1,4);
    lcd_wdat('0'+((init[4]&0xf0)>>4));
    write_position(1,5);
    lcd_wdat('0'+(init[4]&0x0f)); //读月
//    write_position(1,6);
//    lcd_wdat('/');
    write_position(1,7);
    lcd_wdat('0'+((init[3]&0xf0)>>4));
    write_position(1,8);
    lcd_wdat('0'+(init[3]&0x0f)); //读日
    write_position(1,15);
    lcd_wdat('0'+(init[5]&0x0f)); //读周
    flash();
}

/*********************************************************/
// 时间比较
/*********************************************************/
void  Time_compare()
{
//第一次喂食时间
    if(init[2]==0x09)          //如果时间是 09点
                   {
                           if(init[1]==0x10)      // 如果时间是 10分
                                    {
                                        if (init[0]==0x00)    // 如果时间是 00秒
                                                {
                                                         BEEP=0;                      // 开启电机喂食
                                                 //        BEIDENG=0;
                                                
                                                
                                                }
                                    }
                  }
        if(init[2]==0x09)          // 如果时间是 09点
                   {
                           if(init[1]==0x10)          // 如果时间是 10分
                            {
                                        if (init[0]==0x25)          // 如果时间是 25秒
                                                {
                                                     BEEP=1;                      //关闭电机停止喂食
                                                  //BEIDENG=1;
                                                
                                                }
                                   }
                   }
//第二次喂食时间
//开始喂食
    if(init[2]==0x13)          //如果时间是 13点
                   {        
                           if(init[1]==0x00)      // 如果时间是 00分
                            {
                                        if (init[0]==0x00)    // 如果时间是 00秒
                                                {
                                                         BEEP=0;                      // 开启电机喂食
                                                 //        BEIDENG=0;
                                                
                                                }
                               }
                 }
//停止喂食         
         if(init[2]==0x13)          // 如果时间是 13点
                   {
                           if(init[1]==0x00)          // 如果时间是 00分
                            {
                                        if (init[0]==0x25)          // 如果时间是 25秒
                                                {
                                                     BEEP=1;                      //关闭电机停止喂食
                                                  //BEIDENG=1;
                                                }
                                   }
                 }
//第三次喂食时间
    if(init[2]==0x17)          //如果时间是 17点
                   {
                           if(init[1]==0x10)      // 如果时间是 10分
                                    {
                                        if (init[0]==0x00)    // 如果时间是 00秒
                                                {
                                                         BEEP=0;                      // 开启电机喂食
                                                 //        BEIDENG=0;
                                                
                                                
                                                }
                                    }
                  }
        if(init[2]==0x17)          // 如果时间是 17点
                   {
                           if(init[1]==0x10)          // 如果时间是 10分
                            {
                                        if (init[0]==0x25)          // 如果时间是 25秒
                                                {
                                                     BEEP=1;                      //关闭电机停止喂食
                                                  //BEIDENG=1;
                                                
                                                }
                                   }
                   }
//开鱼缸灯时间
//开灯
    if(init[2]==0x17)          //如果时间是 17点
                   {
                           if(init[1]==0x00)      // 如果时间是 00分
                                   {
                                        if (init[0]==0x00)    // 如果时间是 00秒
                                                {
                                                         DENG=0;                      // 开灯
                                                        BEIDENG=0;
                                                        write_position(2,16); lcd_wdat(0x20);
                                                }
                                }
                 }
    if(init[2]==0x21)          // 如果时间是 21点
                   {
                           if(init[1]==0x00)          // 如果时间是 00分
                            {
                                        if (init[0]==0x00)          // 如果时间是 00秒
                                                {
                                                     DENG=1;                      //关灯
                                                        BEIDENG=1;
                                                        write_position(2,16); lcd_wdat(0x00);
                                         
                                                }
                                   }
           }
   }

哪位达人 看看啊?

好象DS1302的时间精度受供电电压有影响,掉电时用电池,电压低点,时钟好象是会走慢。

我估计是不是接错DS1302备用电池的引脚。注意与GND同一侧的VCC引脚【1脚】接主电源,8脚接备用电池。

我估计是不是接错DS1302备用电池的引脚。注意与GND同一侧的VCC引脚【1脚】接主电源,8脚接备用电池。

DS1302这芯片很容易产生自激,它对电压温度很高,稍微一点的波动都会出问题,我以前遇到过很多次,后来我按网上说的换成进口的芯片,就基本不出问题了。

原来如此,我也发现了。掉电后不能正常计时。我刚开始还以为是程序的问题呢

遇到同样的问题 , 看来只能通过买好点的芯片解决问题了 除了1302 还有其他选择吗

学习一下,,,,,,,,,,,,,

我也遇到同样的问题

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top