找回密码
 立即注册
楼主: xiaobendan

弄了一个比较贵的说是原装的DS1302换上了

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:416
  • 最近打卡:2026-07-05 08:36:44
已绑定手机

81

主题

318

回帖

2479

积分

金牌会员

积分
2479
发表于 2026-6-25 12:26:19 | 显示全部楼层
网*** 发表于 2026-6-25 12:12
晶振两端负载电容等效串联的,你只在晶振一端加电容,一个电容容量再大也没多大作用,
还是老老实实按照晶振参 ...

X1端的电容很容易发生不起阵
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:394
  • 最近打卡:2026-07-05 12:28:34

83

主题

7889

回帖

1万

积分

超级版主

积分
16831
发表于 2026-6-25 14:54:23 | 显示全部楼层
xiaob*** 发表于 2026-6-25 11:37
但是很大可能板子几个月都不通电啊,咋办

DS1302里面有SRAM的,记录最后校准的时间。
比如,2026-6-25校准了一次,然后关机。
大约6个月后,比如2026-12-30-12:34:56开机,检测到连续188天没有校准过。
假设10天快45秒,则188天快了846秒=14分6秒,计算好时间为12:20:50,写入DS1302。
同时将2026-12-30写入DS1302的SRAM中。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:416
  • 最近打卡:2026-07-05 08:36:44
已绑定手机

81

主题

318

回帖

2479

积分

金牌会员

积分
2479
发表于 2026-6-25 15:52:52 | 显示全部楼层
梁*** 发表于 2026-6-25 14:54
DS1302里面有SRAM的,记录最后校准的时间。
比如,2026-6-25校准了一次,然后关机。
大约6个月后,比如20 ...

太复杂了,太费脑子了
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:120
  • 最近打卡:2026-07-05 08:00:11
已绑定手机

3

主题

180

回帖

857

积分

高级会员

积分
857
发表于 2026-6-25 17:24:22 | 显示全部楼层
xiaob*** 发表于 2026-6-25 15:52
太复杂了,太费脑子了

长时间断电可以利用单片机低压中断将掉电时的日期保存在DS1302的RAM,待下次上电,用当前日期减上次掉电的日期得到断电天数,再乘以日误差,再用此误差值修正DS1302当前时间。给你一个低压中断保存数据在DS1302的RAM中的示例,稍加修改即可套用。
  1. //测试条件:STC8H实验板,MCU型号STC8H3K48S2
  2. //注意:测试本示例时,需在ISP下载时将【允许低
  3. //压复位(禁止低压中断)】关闭,低压检测电压选3V以上
  4. #include "stc8h.h"            
  5. #include "intrins.h"
  6. typedef unsigned char  u8;
  7. typedef unsigned int   u16;
  8. typedef unsigned long  u32;
  9. sbit SCLK = P5^0;             //DS1302时钟
  10. sbit DSIO = P5^1;             //DS1302数据
  11. sbit REST = P5^2;             //DS1302复位
  12. sbit key1 = P3^3;             //按键1 设置
  13. sbit key2 = P3^2;             //按键2 加
  14. sbit key3 = P3^1;             //按键3 减
  15. sbit key4 = P3^0;             //按键4 读RAM
  16. //DS1302读取和写入时分秒的地址命令---//
  17. u8  code READ_RTC_ADDR [7]= {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; //DS1302读时钟地址/命令
  18. u8  code WRITE_RTC_ADDR[7]= {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //DS1302写时钟地址/命令
  19. //u8  code READD_RAM[]={0xc1,0xc3,0xc5,0xc7,0xc9,0xcb,0xcd,......0xfd};//31字节读RAM地址/命令
  20. //u8  code WRITE_RAM[]={0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,......0xfc};//31字节写RAM地址/命令
  21. //日历缓存   顺序是秒,分,时,日,月,周,年,格式十进制
  22. char data TIME[]={ 30,30,12, 1, 1, 2,24};
  23. u8 code table[]={
  24.         0x3f,0x06,0x5b,0x4f,
  25.         0x66,0x6d,0x7d,0x07,
  26.         0x7f,0x6f,0x77,0x7c,
  27.         0x39,0x5e,0x79,0x71};
  28. u8 data LED_buf[8];           //数码管显存
  29. bit B_1ms;                    //1ms标志
  30. bit flag;                     //标志
  31. u8  Key_value;                //键值
  32. u8  temp;                     //临时
  33. u8  rama,ramb;                //缓冲
  34. u16 num;                      //测试变量
  35. u16 count;                    //计数
  36. bit flicker;                  //闪烁
  37. //DS1302操作函数声明*****************************************
  38. void Ds1302Write(u8 addr, u8 dat);//向1302芯片写入地址和数据
  39. u8   Ds1302Read(u8 addr);     //从1302读数据
  40. void Ds1302ReadTime();        //读取秒分时日月周年信息
  41. void Ds1302Init();            //DS1302初始化
  42. u8   BCD_D(u8 bcd);           //BCD码转十进制函数
  43. u8   D_BCD(u8 Dec);           //十进制转BCD码函数
  44. void Timer0_Init();                          //1毫秒@11.0592MHz
  45. void display();               //显示函数
  46. void key_scan();              //按键扫描
  47. void McuInit();               //初始化端口模式
  48. void McuSleep();              //端口高阻模式
  49. void Delay100ms();            //延时函数
  50. //主函数
  51. void main()
  52. {        
  53.         McuInit();
  54.         Ds1302Init();
  55.         Delay100ms();
  56.         rama=Ds1302Read(0xc1);    //读取RAM中保存的数据
  57.         ramb=Ds1302Read(0xc3);    //读取RAM中保存的数据
  58.         num=rama<<8|ramb;         //合并字节
  59.         PCON &= 0xDF;             //清0掉电标志
  60.         ELVD = 1;                 //开低压中断
  61.         EA   = 1;                 //开总中断
  62.         Timer0_Init();
  63.         while(1)
  64.         {
  65.                 if(B_1ms)             //1ms到
  66.                 {
  67.                         B_1ms = 0;
  68.                         display();        //数码管显示
  69.                         if(Key_value==0)Ds1302ReadTime();//读取Ds1302时间信息
  70.                         if(temp!=TIME[0])
  71.                         {
  72.                                 temp=TIME[0];                //秒更新
  73.                                 if(++num>999)num=0;          //测试数据
  74.                                 flicker=0;                   //秒点复位
  75.                                 count=0;                     //计数复位
  76.                         }
  77.                         LED_buf[0]=table[TIME[2]/10];    //时十位
  78.                         if(flicker)LED_buf[1]=table[TIME[2]%10];//时个位
  79.                         else  LED_buf[1]=table[TIME[2]%10]|0x80;//时个位+秒点
  80.                         LED_buf[2]=table[TIME[1]/10];    //分十位
  81.                         LED_buf[3]=table[TIME[1]%10];    //分个位
  82.                         LED_buf[4]=0x40;                 //"-"
  83.                         LED_buf[5]=table[num/100%10];    //测试数百位
  84.                         LED_buf[6]=table[num/10%10];     //测试数十位
  85.                         LED_buf[7]=table[num%10];        //测试数个位
  86.                         key_scan();                      //按键扫描
  87.                 }
  88.         }
  89. }
  90. //T0中断服务函数
  91. void Timer0_Isr(void) interrupt 1
  92. {
  93.         B_1ms=1;
  94.         if(++count>=500)
  95.                 flicker=1;                //闪烁
  96.         if(count%100==0)
  97.                 flag=~flag;               //快闪
  98. }
  99. void PowerLost() interrupt 6      //低压中断
  100. {
  101.         EA = 0;                       //关闭总中断
  102.         TR0= 0;
  103.         McuSleep();                   //关闭所有不用端口,保留连接Ds1302的端口
  104.         Ds1302Write(0x8e,0x00);       //禁止写保护功能
  105.         Ds1302Write(0xc0,num>>8);     //写num高8位
  106.         Ds1302Write(0xc2,num);        //写num低8位        
  107.         Ds1302Write(0x8e,0x80);       //打开写保护功能
  108. //        P5M0 = 0x00; P5M1 = 0xff;     //关闭连接Ds1302的端口
  109.         while((PCON & 0x20) != 0)     //复查低压标志
  110.         {
  111.                 PCON &= 0xDF;             //清除低压标志
  112.                 _nop_();               
  113.                 _nop_();                  //坐等掉电
  114.         }
  115.         IAP_CONTR = 0x20;             //发现是误报,重启单片机,恢复正常工作
  116. }
  117. void Timer0_Init(void)                      //1毫秒@11.0592MHz
  118. {
  119.         AUXR |= 0x80;                              //定时器时钟1T模式
  120.         TMOD &= 0xF0;                              //设置定时器模式
  121.         TL0 = 0xCD;                                      //设置定时初始值
  122.         TH0 = 0xD4;                                      //设置定时初始值
  123.         TF0 = 0;                                      //清除TF0标志
  124.         TR0 = 1;                                      //定时器0开始计时
  125.         ET0 = 1;                                      //使能定时器0中断
  126. }
  127. //==============DS1302驱动部分=====================
  128. //写1302时钟数据
  129. void Ds1302Write(u8 addr, u8 dat)
  130. {
  131.         u8 i;
  132.         REST= 1;
  133.         for(i=0;i<8;i++)        //写地址/命令
  134.         {
  135.                 DSIO=addr & 0x01;   //数据由低位到高位传送
  136.                 addr>>=1;
  137.                 SCLK = 1;           //数据在上升沿时,DS1302读取数据
  138.                 SCLK = 0;
  139.         }
  140.         for(i=0;i<8;i++)        //写数据
  141.         {
  142.                 DSIO=dat & 0x01;
  143.                 dat>>= 1;
  144.                 SCLK = 1;           //数据在上升沿时,DS1302读取数据
  145.                 SCLK = 0;        
  146.         }                 
  147.         REST = 0;               //传送数据结束        
  148. }
  149. //读1302时钟数据
  150. u8 Ds1302Read(u8 addr)
  151. {
  152.         u8 i,dat,dat1;
  153.         REST = 1;
  154.         for(i=0; i<8; i++)      //开始传送八位地址命令
  155.         {
  156.                 DSIO = addr & 0x01; //数据由低位到高位传送
  157.                 addr >>= 1;
  158.                 SCLK = 1;           //数据在上升沿时,DS1302读取数据
  159.                 SCLK = 0;
  160.         }
  161.         for(i=0;i<8;i++)        // 读取8位数据
  162.         {
  163.                 dat1 = DSIO;        // 从最低位开始接收
  164.                 dat=(dat>>1)|(dat1<<7);
  165.                 SCLK = 1;
  166.                 SCLK = 0;           // 下降沿有效,读取DS1302数据
  167.         }
  168.         REST = 0;
  169.         DSIO = 0;
  170.         return dat;        
  171. }
  172. //初始化DS1302
  173. void Ds1302Init()
  174. {
  175. //        u8 i;
  176.         REST = 0;
  177.         SCLK = 0;
  178.         DSIO = 0;        
  179.         Ds1302Write(0x8E,0x00);   // 禁止写保护功能
  180. //        for(i=0;i<7;i++)          // 写入7个字节的时钟信号:分秒时日月周年
  181. //                Ds1302Write(WRITE_RTC_ADDR[i],D_BCD(TIME[i]));        
  182.         Ds1302Write(0x8E,0x80);   // 打开写保护功能
  183. }
  184. //读取时钟信息
  185. void Ds1302ReadTime()
  186. {
  187.         u8 i;
  188.         for(i=0;i<3;i++)          //读取3个字节的时钟信号:秒分时
  189.                 TIME[i]=BCD_D(Ds1302Read(READ_RTC_ADDR[i]));//BCD转换成十进制保存
  190. }
  191. //BCD码转十进制函数
  192. u8 BCD_D(u8 bcd)
  193. {
  194.         return ((bcd>>4)*10)+(bcd & 0x0f);
  195. }
  196. //十进制转BCD码函数,返回BCD码
  197. u8 D_BCD(u8 Dec)
  198. {
  199.         return (Dec/10*16+Dec%10);
  200. }
  201. //数码管动态显示函数
  202. void display()
  203. {
  204.         static u8 j;                  //循环计数变量
  205.         P0=0x00;                      //消隐
  206.         P2=~(0x01<<j);                //送位码        
  207.         if(Key_value==1 && flag &&(j==0||j==1))
  208.                 P0=0x00;                  //消隐
  209.         else if(Key_value==2 && flag &&(j==2||j==3))
  210.                 P0=0x00;                  //消隐
  211.         else P0=LED_buf[j];           //送段码不加点
  212.         j=++j%8;                      //循环计数
  213. }
  214. //按键扫描函数
  215. void key_scan()
  216. {
  217.         static bit key_sign=0;//按键状态标志
  218.         static u8 count=0;    //消抖计数
  219.         u8 i;
  220.         if(!key1||!key2||!key3||!key4)
  221.         {
  222.                 if(++count>=10 && key_sign==0)
  223.                 {
  224.                         key_sign=1;
  225.                         if(!key1)
  226.                         {
  227.                                 Key_value=++Key_value%3;
  228.                                 if(Key_value==0)
  229.                                 {
  230.                                         Ds1302Write(0x8e,0x00);   // 禁止写保护功能
  231.                                         TIME[0]=0;
  232.                                         for(i=0;i<3;i++)          // 写入3个字节的时钟信号:分秒时
  233.                                                 Ds1302Write(WRITE_RTC_ADDR[i],D_BCD(TIME[i]));        
  234.                                         Ds1302Write(0x8e,0x80);   // 打开写保护功能
  235.                                 }
  236.                         }
  237.                         if(!key2)
  238.                         {
  239.                                 if(Key_value==1)
  240.                                 {
  241.                                         TIME[2]++;
  242.                                         if(TIME[2]>23)TIME[2]=0;
  243.                                 }
  244.                                 if(Key_value==2)
  245.                                 {
  246.                                         TIME[1]++;
  247.                                         if(TIME[1]>59)TIME[1]=0;
  248.                                 }
  249.                         }
  250.                         if(!key3)
  251.                         {
  252.                                 if(Key_value==1)
  253.                                 {
  254.                                         TIME[2]--;
  255.                                         if(TIME[2]<0)TIME[2]=23;
  256.                                 }
  257.                                 if(Key_value==2)
  258.                                 {
  259.                                         TIME[1]--;
  260.                                         if(TIME[1]<0)TIME[1]=59;
  261.                                 }
  262.                         }
  263.                         if(!key4)
  264.                         {
  265.                                 rama=Ds1302Read(0xc1);//读取RAM中保存的数据
  266.                                 ramb=Ds1302Read(0xc3);//读取RAM中保存的数据
  267.                                 num=rama<<8|ramb;
  268.                         }
  269.                 }
  270.         }
  271.         else
  272.         {
  273.                 key_sign=0;
  274.                 count=0;
  275.         }
  276. }
  277. //初始化单片机端口
  278. void McuInit()
  279. {
  280.         P0M0 = 0xff; P0M1 = 0x00;//推挽模式
  281.         P1M0 = 0x00; P1M1 = 0x00;//准双向模式
  282.         P2M0 = 0x00; P2M1 = 0x00;
  283.         P3M0 = 0x00; P3M1 = 0x00;
  284.         P4M0 = 0x00; P4M1 = 0x00;
  285.         P5M0 = 0x00; P5M1 = 0x00;
  286.         P6M0 = 0x00; P6M1 = 0x00;
  287.         P7M0 = 0x00; P7M1 = 0x00;
  288. }
  289. //设置单片机端口省电
  290. void McuSleep()
  291. {
  292.         P0M0 = 0x00; P0M1 = 0x00;//准双向模式
  293. }
  294. void Delay100ms(void)        //@11.0592MHz
  295. {
  296.         unsigned char data i, j, k;
  297.         _nop_();
  298.         i = 6;
  299.         j = 157;
  300.         k = 59;
  301.         do
  302.         {
  303.                 do
  304.                 {
  305.                         while (--k);
  306.                 } while (--j);
  307.         } while (--i);
  308. }
复制代码
无标题456.jpg 无标题123.jpg

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-7-5 14:04 , Processed in 0.071293 second(s), 57 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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