找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6230|回复: 10
收起左侧

带GPS授时语音报时的大数字万年历制作 附单片机程序 DS12C887 DS3231芯片

  [复制链接]
ID:124729 发表于 2020-10-31 04:08 | 显示全部楼层 |阅读模式
制作出来的万年历实物图如下,走时非常精准:

提醒:
1、所有标 C1、C2、C3、R1的元件先不用安装,主要为抗干扰预留,若在使用中不正常才可安装。
2、所有电阻阻值前标“*”表示该电阻可根据LED元件性能或个人使用习惯浮动调节。
3、如果使用mini_USB,需要一定的焊接功夫。可先将焊锡加在5个引脚焊盘上。
4、不能使用劣等供电电源,板子上很多芯片都怕高频干扰!

注意:
1、在有GPS连接的情况下,+、-、EXIT 无效,短按MOD可强制GPS校时。
2、冒号闪烁开关、整点报时开关变量保存入24C02,断电不丢失。
3、调时中,秒不可调整。调到分钟时秒自动回零。
4、调时中可随时按EXIT不保存退出,也可以一直按MOD保存退出。

1.jpg 2.jpg 3.jpg 4.jpg 5.jpg

51hei.png

51hei.png 51hei.png

P0 :DS12C887-AD

//max7219
sbit DIN  = P1^0;
sbit LOAD = P1^1;
sbit CLK  = P1^2;

//控制冒号是否闪烁
sbit BLK  = P1^3;     

//按键 MOD + - EXIT
sbit K1  = P1^4; //K1-调时设置,长按进入时间设置;短按作为日期时间下一项。当gps有效时,短按以gps时间校时
sbit K2  = P1^5; //K2-调时中作+,    运行中作为报时
sbit K3  = P1^6; //K3-调时中作-,    (运行中可留作12/24模式切换)
sbit K4  = P1^7; //K4-调时中作确认、返回;运行中作是否报时选择键

//DS3231,24C02
sbit SCL= P2^0;   
sbit SDA= P2^1;   

P2^2 : DHT11

//语音报时指示灯
sbit SND  = P2^3;

//DS12C887 控制IO
sbit DS  = P2^4;   //兼做电波钟BPC的P0控制
sbit RW  = P2^5;
sbit AS  = P2^6;
sbit CS  = P2^7;

P3^0 :串口RXD
P3^1 :串口TXD

//DS3231 SQW
sbit INT0= P3^2;

//PWM语音芯片
sbit BUSY = P3^3;
sbit DATA = P3^4;
sbit RST  = P3^5;

P3^6 : 红外;
P3^7 : DS18B20;

供电电路:
一、电源预留宽电压输入降压:
1、1117-5
2、7805
若有5V电源,可以将降压芯片输入输出短接。

二、电源输入滤波部分可根据使用的电源质量酌情考虑

三、1.5KE68CA为双向过压保险设计,可无视!

四、部分器件使用3.3V电压,因此使用1117-3.3。输出必须22uF和0.1uF滤波。



24C02是存储冒号是否闪烁及整点报时开关

万年历语音报时芯片与τ 宝原版芯片不一样,地址向后错一位。

原版芯片开机送电产生脉冲即会播报第一个地址“零”,新版定制芯片把第一个地址留空。而且在地址最后额外增加了3个语音:猫叫、老鼠叫、猫叫老鼠叫混合。

语音芯片有3个接口:
SPK1_1、SPK1_2并联,哪个使用方便就接哪个。喇叭建议8Ω/0.25--0.5W
SPK2_1 为放大语音,一般不建议使用。


单片机源程序如下:
  1. //89C52RC + 11.0592M
  2. //语音报时,手动调时,gps授时,电脑校时
  3. //GPS有效信号(VA)稳定达10分钟后自动校时
  4. //电脑可串口发送数据强制校时 GPRMC,024813.640,,,,,,,,150706,X
  5. //                                                         标志头         时分秒                          日月年 标志尾
  6. //DS3231 SQW已引入中断P3.2,但本程序未使用外部中断
  7. //2016.5.10
  8. #include<reg52.h>
  9. #include <intrins.h>
  10. #include <string.h>
  11. #include "DS3231.h"
  12. #include "nongli.h"
  13. #include "iic.h"
  14. /********************************************************************************************************************
  15.                 以下为GPS部分定义
  16. 因时间关系,gps数据应该加校验处理,防止出现乱码情况,虽然gps被干扰的情况很罕见。待其他有精力的玩家来解决
  17. ********************************************************************************************************************/
  18. //GPS数据存储数组
  19. u8 time[6];        //时间
  20. u8 date[6];        //日期
  21. bit va;                           //有效
  22. bit QJ;                           //电脑发送强制校时信号
  23. bit tswc;                   //调时完成标志

  24. //串口中断需要的变量
  25. u8 seg_count;        //逗号计数器
  26. u8 dot_count;        //小数点计数器
  27. u8 byte_count;        //位数计数器

  28. u8 mode;                //0:结束模式,1:命令模式,2:数据模式
  29. u8 buf_full;            //1:整句接收完成,相应数据有效。0:缓存数据无效。
  30. u8 cmd[5];            //命令类型存储数组

  31. typedef  struct        _TIMER          /** 作时区转换时需要用到年、月、日进一 **/
  32. {
  33.     u8 Hour;
  34.     u8 Min;
  35.     u8 Sec;
  36.     u8 Day;
  37.     u8 Mon;
  38.     u8 Year;
  39. } TIMER;
  40. TIMER BjTime;

  41. void InitBps();                           /**  串口初始化 **/
  42. void UTCToLocal(TIMER *GPS_DataTmp);  //时区转换
  43. void Set_DStime(u8 sel);
  44. void GetGpsTime(void);
  45. void FormatString(char *p);
  46. void updatetime();

  47. int gpscount=0;  //gps有效计时

  48. /////////////////////////////////////
  49. sbit DIN  = P1^0;
  50. sbit LOAD = P1^1;
  51. sbit CLK  = P1^2;

  52. sbit BUSY = P3^3;
  53. sbit DATA = P3^4;
  54. sbit RST  = P3^5;

  55. /********按键部分 按键采用定时器配合状态机        **/
  56. bit  TS_Mode;//调时标志
  57. u8   Tcount;  //10ms计数

  58. xdata        uint        F_50ms_Loop                =        0;
  59. xdata        uint        F_500ms_Loop        =        0;

  60. bit        F_50ms        =        1;
  61. bit        F_500ms        =        1;
  62.          
  63. u8   KeyValue;

  64. sbit K1  = P1 ^ 4; //K1-调时设置,长按进入时间设置;短按作为日期时间下一项。当gps有效时,短按以gps时间校时
  65. sbit K2  = P1 ^ 5; //K2-调时中作+,        运行中作为手动报时
  66. sbit K3  = P1 ^ 6; //K3-调时中作-,        运行中作冒号闪烁开关
  67. sbit K4  = P1 ^ 7; //K4-调时中作确认、返回;运行中作整点报时开关

  68. sbit BLK  = P1 ^ 3;         //冒号是否闪烁
  69. sbit SND  = P2 ^ 3;         //语音报时指示灯
  70. bit bs;
  71. bit ss,sb;  //冒号闪烁标志

  72. void key_scan(void);
  73. void Led_Flash(u8 n,bit f);


  74. u8   DStime[8]={0,0,0,0,0,0,0,0};//秒,分,时,周,日,月,年,温度
  75. u8   S[7]={0,0,0,0,0,0,0};//调时时的中间变量

  76. bit sound;//报时指示灯标志 是否允许报时
  77. u8 spkcount;//报时段参数

  78. u8 e;//对应调时的位置
  79. u8  item, max, mini;

  80. void FormatDT();

  81. void Delay_50us(uint t)        //50us延迟函数
  82. {
  83.      u8 j;
  84.          for(;t>0;t--)
  85.           for(j=19;j>0;j--);
  86. }


  87. void speak(uint z)      //赋值变量 Z  Z等于几就播放第几段
  88. {
  89.     RST = 1;                          //语音芯片的复位脚为高电平//
  90.     Delay_50us(4);      //持续 200us//
  91.     RST = 0;                          //然后复位脚置零//
  92.     Delay_50us(4);
  93.         z++;                                /*自己定制语音芯片后移一位,如果使用原版报时芯片,此句应删除*/
  94.     while(z > 0)            //若 Z等于 0 则不工作,若大于 0则继续自减//
  95.     {
  96.         DATA = 1;                  //data 脚位为高电平//
  97.         Delay_50us(3);    //持续 100us//
  98.         DATA = 0;                  //然后置零//
  99.         Delay_50us(3);    //持续 100us这三句的意思就是发从一个 100us的脉冲(高低各 100us)//
  100.         z--;             //z 自减完成后开始播放对应的语音(因为z 是几就播放第几段)//
  101.     }
  102. }

  103. //          八点整
  104. //    八点  零一分
  105. //    八点  十  分
  106. //    八点  十一分
  107. //    八点二十  分
  108. //          八点二十一分
  109. //  十一点
  110. //二十  点
  111. //二十一点
  112. void baoshi()//7--21点报时
  113. {
  114.           if(spkcount<1 || spkcount>9) return;

  115.          

  116. //第二级MAX7219写入字(16位)

  117. void WriteWord_2 (u8 addr, u8 num) //发现与第二及第三块相连的数码管闪烁,增加了空操作后就不闪烁了!!
  118. {
  119.     LOAD = 0;
  120.     _nop_();
  121.     SendChar (NoOp);
  122.     _nop_();
  123.     SendChar (0);

  124.     _nop_();
  125.     SendChar (addr);
  126.     _nop_();
  127.     SendChar (num);
  128.     _nop_();
  129.     SendChar (NoOp);
  130.     _nop_();
  131.     SendChar (0);
  132.     _nop_();

  133.     LOAD = 1;
  134. }

  135. //            向第三级MAX7219写入字(16位)
  136. void WriteWord_1 (u8 addr, u8 num) //发现与第二及第三块相连的数码管闪烁,增加了空操作后就不闪烁了!!
  137. {
  138.     LOAD = 0;
  139.     _nop_();
  140.     SendChar (NoOp);
  141.     _nop_();
  142.     SendChar (0);
  143.     _nop_();
  144.     SendChar (NoOp);
  145.     _nop_();
  146.     SendChar (0);
  147.     _nop_();
  148.     SendChar (addr);
  149.     _nop_();
  150.     SendChar (num);
  151.     _nop_();
  152.     LOAD = 1;
  153. }
  154. void init()
  155. {
  156.     K1 = 1;
  157.     K2 = 1;
  158.     K3 = 1;
  159.     K4 = 1;

  160.         QJ=0;
  161.         SND=1;//关
  162.         sound=0;
  163.         RST=0;
  164.         DATA=0;
  165.         Tcount=0;


  166.         TS_Mode=0;
  167.         KeyValue=0;
  168.         tswc=0;

  169.         ss=Read_02_Data(0);
  170.         Delay_50us(40);

  171.         SND=Read_02_Data(2);
  172.         Delay_50us(40);

  173.         clrwdt;
  174.         bs=0;

  175. }
  176. void InitDis (void)
  177. {
  178.     WriteWord_1 (ScanLimit,ScanDigit-1);        /*设置扫描界限*/
  179.     WriteWord_1 (DecodeMode,DecodeDigit);      /*设置译码模式*/
  180.     WriteWord_1 (Intensity,IntensityGrade);    /*设置亮度*/
  181.     WriteWord_1 (ShutDown,NormalOperation);    /*设置电源工作模式*/
  182.    
  183.     WriteWord_2 (ScanLimit,ScanDigit-2);        /*设置扫描界限*/
  184.     WriteWord_2 (DecodeMode,DecodeDigit);      /*设置译码模式*/
  185.     WriteWord_2 (Intensity,IntensityGrade);   /*设置亮度*/
  186.     WriteWord_2 (ShutDown,NormalOperation);    /*设置电源工作模式*/

  187.     WriteWord_3 (ScanLimit,ScanDigit);         /*设置扫描界限*/
  188.     WriteWord_3 (DecodeMode,DecodeDigit);      /*设置译码模式*/
  189.     WriteWord_3 (Intensity,IntensityGrade);    /*设置亮度*/
  190.     WriteWord_3 (ShutDown,NormalOperation);    /*设置电源工作模式*/
  191. }
  192. /*日期、时间设置函数---------------------------------------------------------*/

  193. void        GetDateTime()        //获取DS3231当前日期和时间
  194. {
  195.                 u8        Tmp,i;
  196.                 for(i=0;i<7;i++)
  197.                 {
  198.                     if(i==3)         //星期不理睬
  199.                            continue;
  200.                         Tmp=read_random(i);        
  201.                         if(i==2)
  202.                                 Tmp&=0x3f;        //时的格式单独处理
  203.                         DStime[i]        =        BCD2HEX(Tmp);               
  204.                 }
  205. }
  206. void        ShowTime(bit b)        //更新信息
  207. {
  208.         WriteWord_2 (Digit4, DStime[0]/10);
  209.         WriteWord_2 (Digit5, DStime[0]%10);
  210.                 if(gpscount)
  211.                 {
  212.                     WriteWord_3 (Digit4, BjTime.Sec/10);   //测试gps走时
  213.                     WriteWord_3 (Digit5, BjTime.Sec%10);
  214.                 }
  215.            if(b) //更新全部信息
  216.            {
  217.                 if(DStime[3]==0 ||DStime[3]==7)         //星期日=8
  218.                         DStime[3]=8;
  219.                 DStime[7]=read_temp() ;

  220.                 WriteWord_2 (Digit0, DStime[2]<10 ? 0x0F:DStime[2]/10);
  221.                 WriteWord_2 (Digit1, DStime[2]%10);
  222.                 WriteWord_2 (Digit2, DStime[1]/10);
  223.                 WriteWord_2 (Digit3, DStime[1]%10);

  224.                         WriteWord_1 (Digit0, DStime[6]/10);
  225.                 WriteWord_1 (Digit1, DStime[6]%10);
  226.                 WriteWord_1 (Digit2, DStime[5]<10?0x0F:1);
  227.                 WriteWord_1 (Digit3, DStime[5]%10);
  228.                 WriteWord_1 (Digit4, DStime[4]<10?0x0F:DStime[4]/10);
  229.                 WriteWord_1 (Digit5, DStime[4]%10);
  230.                 WriteWord_1 (Digit6, DStime[3]);        
  231.         
  232.                 WriteWord_3 (Digit0, month_moon<10? 0x0F:1);
  233.                 WriteWord_3 (Digit1, month_moon%10);
  234.                 WriteWord_3 (Digit2, day_moon<10? 0x0F:day_moon/10);
  235.                 WriteWord_3 (Digit3, day_moon%10);

  236.                         if(!gpscount)
  237.                         {
  238.                         WriteWord_3 (Digit4, 0x0F);   //无湿度计
  239.                         WriteWord_3 (Digit5, 0x0F);
  240.                         }
  241.                 if(DStime[7]<128)//正数时直接显示
  242.                 {
  243.                                 WriteWord_3 (Digit6, DStime[7] / 10);
  244.                                 WriteWord_3 (Digit7, DStime[7] % 10);
  245.                 }
  246.                 else
  247.                 {
  248.                                 WriteWord_3 (Digit6, 0x0A);//负数显示 -
  249.                                 WriteWord_3 (Digit7, DStime[7] % 10);        //零下只显示一位        
  250.                 }        

  251.                 }
  252. }
  253. void        Led_Flash(u8 n,bit f)        //调试时闪烁提示效果
  254. {
  255.     if(n < 3)
  256.     {
  257.         if(f)
  258.         {
  259.             WriteWord_1 (n*2 + 1, 0x0F);
  260.             WriteWord_1 (n*2 + 2, 0x0F);
  261.         }
  262.         else
  263.         {
  264.             WriteWord_1 (n*2 + 1, S[n] / 10);
  265.             WriteWord_1 (n*2 + 2, S[n] % 10);
  266.         }                                                                                                                                                                                                                                                                                                                        
  267.     }
  268.     else
  269.     {
  270.                 if(f)
  271.         {
  272.             WriteWord_2 ((n-4)*2 + 1, 0x0F);
  273.             WriteWord_2 ((n-4)*2 + 2, 0x0F);

  274.         }
  275.         else
  276.         {
  277.             WriteWord_2 ((n-4)*2 + 1, S[n] / 10);
  278.             WriteWord_2 ((n-4)*2 + 2, S[n] % 10);
  279.         }

  280.     }
  281. }
  282. void updatetime()
  283. {
  284.         u8 i;
  285.                 S[3]= Conver_WEEK( S[0], S[1], S[2]);
  286.                 if(S[3]== 0)
  287.                    S[3]=7;
  288.         for(i = 0; i < 7; i++)
  289.         {
  290.             if(S[i] != DStime[6-i])
  291.                 ModifyTime(6-i, S[i]);
  292.         }
  293. }
  294. //按键扫描,定时10ms执行一次
  295. static u8 KeyScan(void)
  296. {
  297.     if(K1 == 0)return KEY_VALUE_1 ;
  298.     if(K2 == 0)return KEY_VALUE_2 ;
  299.     if(K3 == 0)return KEY_VALUE_3 ;
  300.     if(K4 == 0)return KEY_VALUE_4 ;
  301.     return KEY_NULL ;
  302. }
  303. u8  GetKey(void)
  304. {
  305.     static u8 s_u8KeyState = KEY_STATE_INIT ;
  306.     static u8 s_u8KeyTimeCount = 0 ;
  307.     static u8 s_u8LastKey = KEY_NULL ;  //保存按键释放时候的键值
  308.     u8 KeyTemp = KEY_NULL ;
  309.     KeyTemp = KeyScan() ;        //获取键值
  310.     switch(s_u8KeyState)
  311.     {
  312.             case KEY_STATE_INIT :
  313.             {
  314.                 if(KEY_NULL != (KeyTemp))
  315.                 {
  316.                     s_u8KeyState = KEY_STATE_WOBBLE ;
  317.                 }
  318.             }
  319.             break ;
  320.             case KEY_STATE_WOBBLE :      //消抖
  321.             {
  322.                 s_u8KeyState = KEY_STATE_PRESS ;
  323.             }
  324.             break ;
  325.             case KEY_STATE_PRESS :
  326.             {
  327.                 if(KEY_NULL != (KeyTemp))
  328.                 {
  329.                     s_u8LastKey = KeyTemp ; //保存键值,以便在释放按键状态返回键值
  330.                     KeyTemp |= KEY_DOWN ;  //按键按下
  331.                     s_u8KeyState = KEY_STATE_LONG ;
  332.                 }
  333.                 else
  334.                 {
  335.                     s_u8KeyState = KEY_STATE_INIT ;
  336.                 }
  337.             }
  338.             break ;
  339.             case KEY_STATE_LONG :
  340.             {
  341.                 if(KEY_NULL != (KeyTemp))
  342.                 {
  343.                     if(++s_u8KeyTimeCount > KEY_LONG_PERIOD)
  344.                     {
  345.                         s_u8KeyTimeCount = 0 ;
  346.                         KeyTemp |= KEY_LONG ;  //长按键事件发生
  347.                         s_u8KeyState = KEY_STATE_CONTINUE ;
  348.                     }
  349.                 }
  350.                 else
  351.                 {
  352.                     s_u8KeyState = KEY_STATE_RELEASE ;
  353.                 }
  354.             }
  355.             break ;
  356.             case KEY_STATE_CONTINUE :
  357.             {
  358.                 if(KEY_NULL != (KeyTemp))
  359.                 {
  360.                     if(++s_u8KeyTimeCount > KEY_CONTINUE_PERIOD)
  361.                     {
  362.                         s_u8KeyTimeCount = 0 ;
  363.                         KeyTemp |= KEY_CONTINUE ;
  364.                     }
  365.                 }
  366.                 else
  367.                 {
  368.                     s_u8KeyState = KEY_STATE_RELEASE ;
  369.                 }
  370.             }
  371.             break ;
  372.             case KEY_STATE_RELEASE :
  373.             {
  374.                 s_u8LastKey |= KEY_UP ;
  375.                 KeyTemp = s_u8LastKey ;
  376.                 s_u8KeyState = KEY_STATE_INIT ;
  377.             }
  378.             break ;
  379.             default :
  380.                 break ;
  381.     }
  382.     return KeyTemp ; //返回键值
  383. }
  384. void  KeyProc(void)
  385. {
  386.                 u8 i;
  387.         if(!va && !TS_Mode && KeyValue == (KEY_VALUE_1 | KEY_LONG))   //无gps+长按K1进入调时
  388.         {
  389.             TS_Mode = 1;                //进入调时模式
  390.             for(i = 0; i < 7; i++)         
  391.             {
  392.                 S[i] = DStime[6 - i];
  393.             }
  394.         }

  395.         if(KeyValue == (KEY_VALUE_1 | KEY_DOWN))
  396.         {
  397.             if(TS_Mode)                //在调时状态下进入下一项设置
  398.             {
  399.                 if(S[e] != DStime[6 - e] || e>4)
  400.                 {
  401.                     ModifyTime(6 - e, S[e]);
  402.                     DStime[6 - e] = S[e];
  403.                 }
  404.                                 
  405.                 e++;
  406.                 if(e == 3) //跳过调整星期
  407.                     e++;

  408.                 if (e == 5)        //调到分钟时,秒置零
  409.                 {
  410.                                         S[6]=0;
  411.                             WriteWord_2 (5, 0);
  412.                             WriteWord_2 (6, 0);
  413.                                 }
  414.                 if (e > 5)
  415.                 {
  416.                     ModifyTime(0, 0);
  417.                                         e = 0;
  418.                     TS_Mode = 0;                                //修改退出
  419.                                         tswc=1;                                       
  420.                 }
  421.             }

  422.             if(va)                   //有gps按下即强制校时
  423.             {
  424.                 GetGpsTime();
  425.                 updatetime();
  426.             }
  427.         }

  428.         if(KeyValue == (KEY_VALUE_2 | KEY_DOWN))        //+
  429.         {
  430.             if(TS_Mode)
  431.             {
  432.                 item = S[e];
  433.                 item++;//数加 1
  434.                 Set_DStime(e);
  435.             }
  436.             else //运行中做报时键
  437.             {
  438.                 sound = 1;
  439.                 spkcount = 9;
  440.             }
  441.         }
  442.         if(KeyValue == (KEY_VALUE_3 | KEY_DOWN))        //-
  443.         {
  444.             if(TS_Mode)
  445.             {
  446.                 item = S[e];
  447.                                 if(item == 0)
  448.                                 {
  449.                                         if(e==4)
  450.                                                 item=23;
  451.                                          else
  452.                                                 item=59;
  453.                                 }
  454.                                 else
  455.                 item--;//数减 1
  456.                 Set_DStime(e);
  457.             }
  458.                         else
  459.                         {
  460.                                 ss=~ss;         //闪烁
  461.                                 sb=1;
  462.                         }
  463.         }

  464.         if(KeyValue == (KEY_VALUE_4 | KEY_DOWN))        //EXIT
  465.         {
  466.             if(TS_Mode)
  467.             {
  468.                 TS_Mode = 0;                       //退出调时
  469.                 e = 0;                                   //"下一项"计数器清0
  470.                 //updatetime();
  471.                                 tswc=1;
  472.             }
  473.             else
  474.             {
  475.                 SND = ~SND;                          /**  运行模式中 K4 作语音报时切换键  **/
  476.                                 bs=1;                                
  477.             }
  478.         }
  479. }

  480. void main()//主函数
  481. {
  482.     u8 Temp, TempT;
  483.     u8 i = 0;
  484.     u8 ee = 0;
  485.     bit d = 0;
  486.     e = 0;
  487.     TempT = Temp = 0;

  488.     init();
  489.     InitDis ();
  490.     InitBps();
  491.     Delayms(100);

  492.     GetDateTime();

  493.     Conversion( DStime[6], DStime[5], DStime[4]);
  494.     DStime[3] = Conver_WEEK( DStime[6], DStime[5], DStime[4]);
  495.     ShowTime(1);

  496.     BLK = 0;
  497.     clrwdt;
  498.         

  499.     while(1)//进入无限循环
  500.     {
  501.         if(TS_Mode  == 0)         //运行模式
  502.         {
  503.             if(F_50ms)        //50ms标志
  504.             {
  505.                 GetDateTime();
  506.                 F_50ms        =        0;
  507.             }

  508.             if(QJ)        //电脑发送的校时信息
  509.             {
  510.                 GetGpsTime();
  511.                 updatetime();
  512.                                 tswc=1;
  513.                 QJ = 0;
  514.             }

  515.             if(Temp != DStime[0]) //不用频繁更新,有变化才更新一次
  516.             {
  517.                 if(va && TempT != BjTime.Sec) //如果接收到GPRMC有效数据
  518.                 {
  519.                     TempT = BjTime.Sec;
  520.                     if(gpscount++ == 600) //持续有效达10分钟即自动校时,可根据GPS性能调整
  521.                     {
  522.                         GetGpsTime();
  523.                         updatetime();
  524.                     }
  525.                     if(gpscount > 86400) //若gps挂机超过1天则回零
  526.                         gpscount = 0;
  527.                 }
  528.                 else
  529.                 {
  530.                     gpscount = 0;
  531.                     va = 0;
  532.                 }

  533.                 if(DStime[0] == 0 ||  tswc)  //每分钟或调时完成全部刷新
  534.                 {
  535.                     if(DStime[1] == 0)        //每小时
  536.                     {
  537.                         //Conversion( DStime[6], DStime[5], DStime[4]);
  538.                         //DStime[3]        = Conver_WEEK( DStime[6], DStime[5], DStime[4]);
  539.                         
  540.                         if(DStime[2] > 6 && DStime[2] < 22 )        //7--21点报时
  541.                         {
  542.                             InitDis ();//每小时初始化一次
  543.                                                         if(!SND )
  544.                                                         {
  545.                                                                 sound = 1;         //整点报时
  546.                                     spkcount = 9;
  547.                                                         }
  548.                         }
  549.                                                 else  //夜间节能模式
  550.                                                 {
  551.                                                         WriteWord_1 (Intensity,0);
  552.                                                         WriteWord_2 (Intensity,0);
  553.                                                         WriteWord_3 (Intensity,0);
  554.                                                 }

  555.                     }
  556.                     Conversion( DStime[6], DStime[5], DStime[4]);
  557.                     DStime[3]        = Conver_WEEK( DStime[6], DStime[5], DStime[4]);
  558.                     ShowTime(1); //每分钟全部更新一次 ,调整完时间退出后全部更新一次
  559.                     if(tswc)
  560.                     {
  561.                                                 tswc = 0;
  562.                     }
  563.                     
  564.                 }
  565.                 else
  566.                     ShowTime(0);  //只更新秒

  567.                 Temp = DStime[0];

  568.                                 if(sb)
  569.                                 {
  570.                                   Write_02_Data(0,ss);
  571.                                   Delay_50us(40);
  572.                                   sb=0;                                                                  
  573.                                 }
  574.                                 if(ss)
  575.                         BLK=~BLK;          //开启冒号闪烁
  576.             }
  577.             if(sound && BUSY)
  578.             {
  579.                 baoshi();
  580.                 if(spkcount < 1 || spkcount > 20 )
  581.                     sound = 0; //退出报时
  582.             }
  583.                         if(bs) //报时存储
  584.                         {
  585.                                   Write_02_Data(2,SND);
  586.                                   Delay_50us(40);
  587.                                   bs=0;
  588.                         }

  589.         }
  590.         else
  591.         {
  592.             //调试状态,led应闪烁指示调整位
  593.             if(F_500ms)        //500ms标志
  594.             {
  595.                 d = ~d;
  596.                 if(e != ee )   //调整下一项时防止上一项不亮
  597.                 {
  598.                     Led_Flash(ee, 0);
  599.                     ee = e;
  600.                 }
  601.                 Led_Flash(e, d);

  602.                 F_500ms        =        0;
  603.             }
  604.             //if()        //进入调时超过5分钟后自动退出 (该功能略)
  605.         }
  606.         clrwdt;        //设置看门狗
  607.     }
  608. }

  609. /*-----------------------------日期、时间设置函数-----------------------------*/
  610. //被调数据加一或减一,并检查数据范围,写入3231指定地址保存
  611. void ds_w(u8 sel)
  612. {
  613.     if(item > max) item = mini;         //查看数值是否在有效范围之内
  614.     if(item < mini) item = max;         //如果数值小于最小值,则自动等于最大值
  615.         S[sel]=item;
  616. }
  617. void Set_DStime(u8 sel)  //根据选择调整的相应项目加1并写入DS3231,函数参数是按动设置键的次数
  618. {
  619.     if(sel == 3 || sel == 6)  return; //星期不用设置
  620.         /*        秒不用设置,调到分钟时,秒置零
  621.         if(sel == 6)
  622.     {
  623.         max = 59;
  624.         mini = 0;
  625.         ds_w(sel);                  //被调数据加一或减一函数
  626.     }        
  627.         //秒7,按动7次显示 调整秒钟
  628.     //秒钟数据的最大值是59,最小值是0
  629.         */

  630.     if(sel == 5)
  631.     {
  632.         max = 59;
  633.         mini = 0;
  634.         ds_w(sel);

  635.     }        
  636.         //分钟6,按动6次显示 调整分钟
  637.     //分钟数据的最大值是59,最小值是0

  638.     if(sel == 4)
  639.     {
  640.         max = 23;
  641.         mini = 0;
  642.         ds_w(sel);

  643.     }        //小时5,按动5次显示 调整小时
  644.     //小时数据最大值23,最小值是0        

  645.     if(sel == 2)
  646.     {
  647.         if(S[1] == 2 && S[0] % 4 != 0)
  648.         {
  649.             max = 28;    //平年2月28天
  650.             mini = 1;
  651.         }
  652.         if(S[1] == 2 && S[0] % 4 == 0)
  653.         {
  654.             max = 29;    //闰年2月29天
  655.             mini = 1;
  656.         }
  657.         if(S[1] == 1 || S[1] == 3 || S[1] == 5 || S[1] == 7 || S[1] == 8 || S[1] == 10 || S[1] == 12)
  658.         {
  659.             max = 31;    //31天的月份
  660.             mini = 1;
  661.         }
  662.         if(S[1] == 4 || S[1] == 6 || S[1] == 9 || S[1] == 11)
  663.         {
  664.             max = 30;    //30天的月份
  665.             mini = 1;
  666.         }
  667. ……………………

  668. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
51hei.png
所有资料51hei提供下载:
万年历.7z (3.73 MB, 下载次数: 175)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:489631 发表于 2020-10-31 10:42 | 显示全部楼层
感谢分享,最好能附上原理图和打板文件
回复

使用道具 举报

ID:207943 发表于 2020-10-31 21:49 | 显示全部楼层
感谢分享,这个有点大
回复

使用道具 举报

ID:64053 发表于 2021-3-2 01:02 | 显示全部楼层
一乐原创
回复

使用道具 举报

ID:884042 发表于 2021-8-19 14:50 | 显示全部楼层
语音芯片建议用NVC080C系列的,可以改音量,内存也很大,资料上网找
回复

使用道具 举报

ID:1011444 发表于 2022-5-23 13:20 | 显示全部楼层
描述的很详细,楼主辛苦!实际制作大部分都是贴片器件,焊接任务太大了,不易成功,不过还是要谢谢分享
回复

使用道具 举报

ID:1011444 发表于 2022-6-7 17:52 | 显示全部楼层
资料丰富齐全,表述清晰明了,多谢分享!
回复

使用道具 举报

ID:1011444 发表于 2022-7-14 12:13 | 显示全部楼层
今天仔细看了一遍,感觉大数码管电源5v电压似乎驱动不了,四个led串联至少要有7v以上的电压才可点亮,如何设计电源?应有详细描述。
回复

使用道具 举报

ID:1039479 发表于 2022-7-14 14:16 | 显示全部楼层
jdf 发表于 2020-10-31 10:42
感谢分享,最好能附上原理图和打板文件

非常好用
回复

使用道具 举报

ID:149642 发表于 2022-7-22 09:17 | 显示全部楼层
kz0018 发表于 2022-5-23 13:20
描述的很详细,楼主辛苦!实际制作大部分都是贴片器件,焊接任务太大了,不易成功,不过还是要谢谢分享

贴片的最好焊了,胶水粘上热风枪随便吹吹就好
回复

使用道具 举报

ID:1064915 发表于 2023-10-28 17:45 | 显示全部楼层
请教GPS模块是哪个?
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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