找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10082|回復(fù): 25
收起左側(cè)

DS1302電波鐘制作 附單片機源程序

  [復(fù)制鏈接]
ID:744744 發(fā)表于 2020-6-20 16:36 | 顯示全部樓層 |閱讀模式
1、本人對單片機編程不在行,也是在不斷學(xué)習(xí)中,我是搞硬件工作的,對一般的硬件電路倒是很熟悉,也用單片機做個一些非常簡單的項目,比如一些試驗設(shè)備也是用單片機來控制,事半功倍啊。但那些程序相對IIC,紅外通信,1302來說都簡單得不得了。本著利用業(yè)余時間不斷學(xué)習(xí)精進(jìn)的理想,一直在努力向前輩們學(xué)習(xí)中。平日里自己的作品都不能留在自己的手上,就像看著自己的兒子被人抱走一樣,也許沒什么技術(shù)含量,但自娛自樂一下,還是能提升不少荷爾蒙,為了彌補心中之遺憾,特別做一件留給自己的作品。
我不喜歡在開發(fā)板上作東西,那是開發(fā)前期試驗程序用的,不能算是一件作品。一件作品必須是獨立的實現(xiàn)預(yù)設(shè)的功能指標(biāo),所有的相關(guān)設(shè)計都是圍繞這個功能為中心,并且作品具有一定的實用性和便利性。

該作品硬件比較簡單,但程序部分花了我不少時間(因為是新手),電波鐘解碼部分找了些網(wǎng)上的相關(guān)解決方案和電波鐘的信號編碼規(guī)則,結(jié)合到手上1的程序,試驗調(diào)試,解決各種BUG,最后完成。

2、材料清單:
1、STC12CXXXX單片機一片
2、1英寸白色數(shù)碼管和紅色小數(shù)碼管共6只
3、74HC245一塊
4、DS1302模塊(用的現(xiàn)成的)一塊
5、報時語音模塊一塊
6、電波鐘模塊一塊
7、運放一塊
8、光敏,發(fā)光二極管,PNP和NPN數(shù)只,按鍵4只,
9、連接線若干
10、透明防水外殼一個
11、杜幫線若干
12、9V線性變壓電源一只
13、7805一塊,SM1117一塊
14、電解電容,鉭電容,電阻,貼片電阻容若干
15、洞洞板一塊,銅柱4根
16、防浪涌保護(hù)TVS管一只

3、開始工作
準(zhǔn)備構(gòu)思如何用好這些材料做出一個像樣的作品,前殼為什么要全透明呢,這是為了增加電子作品的藝術(shù)性,觀賞性(手工板也可以欣賞)能看清內(nèi)部構(gòu)造,即增加了作品的透明感,又增加了電子技術(shù)的神秘感。

初步構(gòu)思

初步構(gòu)思

理想中,成品應(yīng)該可能也許大概是這樣的

焊接部分模塊

焊接部分模塊

焊接幾個,試試效果,不斷構(gòu)思,不斷改進(jìn)中。先用的綠色LED作為時分的分隔,后來發(fā)現(xiàn)綠光不純,偏黃,后換成紅色。

再次構(gòu)思

再次構(gòu)思

經(jīng)過一天的焊接(業(yè)余時間),初步成型,先試試能不能動起來。嗯,不完美的地方來了,LED看起來亮與不亮的字段區(qū)分不明顯,對于我這個強迫癥來說,一定要加濾光片。不然難受,吃不下飯。
IMG_20200619_131721.jpg
不管了,先把電波鐘模塊加上,淘寶15元。用熱熔膠粘上去。語音模塊也裝上,喇叭也在側(cè)面開了孔。電波模塊用LED試驗了一下,晚上能收到信號,白天基本不可能,電磁污染太嚴(yán)重(我就是搞EMC的),經(jīng)我試驗,坐標(biāo)廣州,收到商丘的電波鐘信號,要在晚上00點以后,才能在窗戶口收到正常的信號。
IMG_20200620_112000.jpg

取個名《大笨鐘》,LED已經(jīng)加了濾光片,現(xiàn)在已經(jīng)完美了。按鍵加上了,電波的電源控制等部分也完成了。寫入程序,增加自己功能,并調(diào)試。白LED太亮,晚上就是小夜燈,所以在夜間要降低亮度,用光敏加運放自動控制。

IMG_20200620_113738.jpg

紅色LED在電波對時成功后會關(guān)閉,綠色LED是電波鐘信號指示,會隨信號有無閃動。夜間2-3點自動開啟授時,授時失敗紅色LED亮起提示,直到第二次授時成功后,才會關(guān)閉。第4個按鍵改為強制手動授時。本來第4個鍵是手動關(guān)閉整點報時的,F(xiàn)在程序改為夜間自動關(guān)閉報時

IMG_20200620_113956.jpg

最終完成,放在古董收音機上,不錯。為什么我的按鍵要放在里面呢,調(diào)時要開蓋,不方便??NONO,我的是電波授時,理論上,永遠(yuǎn)不用調(diào)時。所以不需要開蓋調(diào)整。我也不需要年月日周,所以只要時間就OK。
IMG_20200620_114514.jpg

以下是程序部分,發(fā)程序出來,不注釋,別人很難看懂,隔幾個月,自己可能都看不懂了。哈哈哈。

嚴(yán)正聲明:本程序部分純屬個人技術(shù)性開發(fā)娛樂,無任何商業(yè)用途,如認(rèn)為有侵權(quán)行為,速與我聯(lián)系或與論壇管理員聯(lián)系并刪除。否則本人不承擔(dān)任何法律責(zé)任。

/**************************************************
程序名:《大笨鐘》
晶  振:24MHZ
功  能:LED數(shù)碼管顯示,按鍵可調(diào),電波自動校時,整點報時功能,夜間光感自動亮度
全局變量已達(dá)到90個,有點多,后續(xù)要完善一下,只用一個程序文件寫完。
******************************************************/
  1. /**************************************************
  2. 程序名:《大笨鐘》
  3. 晶  振:24MHZ
  4. 功  能:LED數(shù)碼管顯示,按鍵可調(diào),電波自動校時,整點報時功能,夜間光感自動亮度

  5. 全局變量已達(dá)到93個

  6. ******************************************************/
  7. #include<stc12c5a60s2.h>
  8. #include<intrins.h>

  9. #define uchar unsigned char
  10. #define uint unsigned int

  11. uchar Dat_su,Dat_num,min,hour,keysetnum;
  12. uchar s1,m1,h1;
  13. uchar hourshi,hourge,minshi,minge,secshi,secge;

  14. sbit DSIO = P2^2;          //1302信號腳
  15. sbit RST  = P2^1;          //1302復(fù)位信號腳
  16. sbit SCLK = P2^0;          //1302時鐘信號腳

  17. sbit keyset = P3^7;           //進(jìn)入設(shè)置
  18. sbit keyshi = P3^6;           //時加按鍵設(shè)置
  19. sbit keyfen = P3^5;           //分加按鍵設(shè)置
  20. sbit keyBPC = P3^4;           //電波強制對時按鍵
  21. sbit Ring   = P2^4;           //整點報時輸出

  22. bit flag200ms;         //200MS讀DS1302標(biāo)志位
  23. bit keysetflag;         //進(jìn)入按鍵設(shè)置標(biāo)志位
  24. bit alarmflag;         //報時標(biāo)志位

  25. /******BPC***********/
  26. sbit BPC    = P3^3;         //BPC輸入,外部輸入
  27. sbit BPC_EN = P2^3;          //BPC 使能
  28. sbit BPC_FailLED = P2^5;         //BPC校時失敗指示燈
  29. bit keyBPCflag;                         //強制對時標(biāo)志位
  30. bit BPC_add;                         //BPC中斷標(biāo)志位
  31. bit BPC_ok = 1;            //對時成功標(biāo)志位,默認(rèn)為開啟才能開啟BPC
  32. bit Get_time,As_time;          //授時標(biāo)志位
  33. uchar Dat_su,Dat_num,keyBPCnum;
  34. uchar data BPC_dat[3][19];         //BPC3列個19組數(shù)組
  35. uint BPC_temp,Dat_add;                  //BPC脈寬時間記錄變量
  36. uchar data Times[3];  //BPC "分,時,上/下午“數(shù)組


  37. uchar DisplayData[6];        //LED顯示緩存數(shù)組
  38. uchar code smgduan[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0x78,0x80,0x90};        //LED 0-9

  39. //DS1302寫入和讀取時分秒的地址命令
  40. //秒分時日月周年最低位讀寫位
  41. uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
  42. uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

  43. //存儲順序秒分時日月周年,存儲格式是用BCD碼//
  44. uchar TIME[7];


  45. /*************************************
  46. * 函數(shù)名: delay()
  47. * 按鍵延時函數(shù),按鍵使用
  48. ************************************/
  49. void delay()           //100ms
  50. {                                 
  51.     unsigned char a,b,c;
  52.     for(c=4;c>0;c--)
  53.         for(b=212;b>0;b--)
  54.             for(a=140;a>0;a--);
  55. }

  56. /*******************************************************************************
  57. * 函 數(shù) 名         : Ds1302Write
  58. * 函數(shù)功能                   : 向DS1302命令(地址+數(shù)據(jù))
  59. * 輸    入         : addr,dat
  60. *******************************************************************************/

  61. void Ds1302Write(uchar addr, uchar dat)
  62. {
  63.         uchar n;
  64.         RST = 0;
  65.         _nop_();

  66.         SCLK = 0;               //先將SCLK置低電平。
  67.         _nop_();
  68.         RST = 1;                //然后將RST(CE)置高電平。
  69.         _nop_();

  70.         for (n=0; n<8; n++)     //開始傳送八位地址命令
  71.         {
  72.                 DSIO = addr & 0x01;//數(shù)據(jù)從低位開始傳送
  73.                 addr >>= 1;
  74.                 SCLK = 1;          //數(shù)據(jù)在上升沿時,DS1302讀取數(shù)據(jù)
  75.                 _nop_();
  76.                 SCLK = 0;
  77.                 _nop_();
  78.         }
  79.         for (n=0; n<8; n++)   //寫入8位數(shù)據(jù)
  80.         {
  81.                 DSIO = dat & 0x01;
  82.                 dat >>= 1;
  83.                 SCLK = 1;         //數(shù)據(jù)在上升沿時,DS1302讀取數(shù)據(jù)
  84.                 _nop_();
  85.                 SCLK = 0;
  86.                 _nop_();        
  87.         }        
  88.                  
  89.         RST = 0;              //傳送數(shù)據(jù)結(jié)束
  90.         _nop_();
  91. }

  92. /*******************************************************************************
  93. * 函 數(shù) 名         : Ds1302Read
  94. * 函數(shù)功能                   : 讀取一個地址的數(shù)據(jù)
  95. * 輸    入         : addr
  96. * 輸    出         : dat
  97. *******************************************************************************/

  98. uchar Ds1302Read(uchar addr)
  99. {
  100.         uchar n,dat,dat1;
  101.         RST = 0;
  102.         _nop_();

  103.         SCLK = 0;              //先將SCLK置低電平。
  104.         _nop_();
  105.         RST = 1;               //然后將RST(CE)置高電平。
  106.         _nop_();

  107.         for(n=0; n<8; n++)     //開始傳送八位地址命令
  108.         {
  109.                 DSIO = addr & 0x01;//數(shù)據(jù)從低位開始傳送
  110.                 addr >>= 1;
  111.                 SCLK = 1;          //數(shù)據(jù)在上升沿時,DS1302讀取數(shù)據(jù)
  112.                 _nop_();
  113.                 SCLK = 0;          //DS1302下降沿時,放置數(shù)據(jù)
  114.                 _nop_();
  115.         }
  116.         _nop_();
  117.         for(n=0; n<8; n++)    //讀取8位數(shù)據(jù)
  118.         {
  119.                 dat1 = DSIO;      //從最低位開始接收
  120.                 dat = (dat>>1) | (dat1<<7);
  121.                 SCLK = 1;
  122.                 _nop_();
  123.                 SCLK = 0;        //DS1302下降沿時,放置數(shù)據(jù)
  124.                 _nop_();
  125.         }

  126.         RST = 0;
  127.         _nop_();               //DS1302復(fù)位的穩(wěn)定時間,必須的。
  128.         SCLK = 1;
  129.         _nop_();
  130.         DSIO = 0;
  131.         _nop_();
  132.         DSIO = 1;
  133.         _nop_();
  134.         return dat;        
  135. }

  136. /*******************************************************************************
  137. * 函 數(shù) 名         : Ds1302Init
  138. * 函數(shù)功能                   : 初始化DS1302  

  139. *******************************************************************************/

  140. void Ds1302Init()
  141. {
  142.         uchar dat;
  143.         RST = 0;
  144.     SCLK = 0;
  145.         dat = Ds1302Read(0x81);                 //讀1302最高位判斷掉電時間是否正常
  146.         if((dat&0x80)!=0)                           //為0,正常運行
  147.          {
  148.                  Ds1302Write(0x8E,0X00);                 //禁止寫保護(hù),就是關(guān)閉寫保護(hù)功能
  149.                 Ds1302Write(0x84,0x00);                  //寫入時鐘最高位為0,定義為24小時制
  150.                
  151.                 /******
  152.                 本程序不需要寫入年月日和初始時間
  153.                 for (n=0; n<7; n++)          //寫入7個字節(jié)的時鐘信號:分秒時日月周年
  154.             {
  155.                         Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);        
  156.                 }
  157.                 *******/
  158.                 Ds1302Write(0x8E,0x80);                 //打開寫保護(hù)功能
  159.         }         
  160. }

  161. /*******************************************************************************
  162. * 函 數(shù) 名         : Ds1302ReadTime
  163. * 函數(shù)功能                   : 讀取時鐘信息

  164. *******************************************************************************/

  165. void Ds1302ReadTime()
  166. {
  167.         uchar n;
  168.         for (n=0; n<7; n++)    //讀取7個字節(jié)的時鐘信號:分秒時日月周年
  169.         {
  170.                 TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
  171.         }
  172.                
  173. }


  174. /*******************************************************************************
  175. * 函 數(shù) 名         : datapros()
  176. * 函數(shù)功能                   : 時間讀取處理轉(zhuǎn)換函數(shù)

  177. *******************************************************************************/

  178. void datapros()         
  179. {
  180.            Ds1302ReadTime();  //先讀取1302的時分秒
  181.         DisplayData[0] = smgduan[TIME[2]>>4];       //時十位                                    
  182.         DisplayData[1] = smgduan[TIME[2]&0x0f];                                 
  183.         DisplayData[2] = smgduan[TIME[1]/16];                //分十位
  184.         DisplayData[3] = smgduan[TIME[1]&0x0f];        
  185.         DisplayData[4] = smgduan[TIME[0]/16];                 //秒十位
  186.         DisplayData[5] = smgduan[TIME[0]&0x0f];
  187. }


  188. /*******************************************************************************
  189. * 函 數(shù) 名         :keyscan()
  190. * 函數(shù)功能                   :按鍵設(shè)置時間和BPC對時

  191. *******************************************************************************/
  192. void keyscan()
  193. {
  194.         if(keyset == 0)
  195.         {
  196.                 delay();
  197.                 if(keyset == 1)
  198.                   {                          
  199.                           keysetnum++;         //按鍵記錄值
  200.                         h1 = (TIME[2]>>4)*10+(TIME[2]&0x0f)%10;//先將1302暫停時的小時值轉(zhuǎn)換成十進(jìn)制賦予變量H1時,以便在此基礎(chǔ)上累加調(diào)整改然后寫入1302
  201.                         m1 = (TIME[1]>>4)*10+(TIME[1]&0x0f)%10;//先將1302暫停的的分鐘值轉(zhuǎn)換成十進(jìn)制賦予變量M1時,以便在此基礎(chǔ)上累加調(diào)整改然后寫入1302                    
  202.                   }
  203.                   if(keysetnum == 1)         //按一次
  204.                   {
  205.                           keysetflag = 1;           //按下KEYSET標(biāo)志位,用以暫停讀1302
  206.                   }
  207.                   if(keysetnum >= 2)   //按二次,恢復(fù)讀1302,不能==2,可能因按鍵因素大于2
  208.                   {
  209.                           keysetnum = 0;                //清零
  210.                         keysetflag = 0;                //標(biāo)志位清零,恢復(fù)讀1302        
  211.                         Ds1302Write(0x8E,0X00);         //關(guān)閉1302寫保護(hù)
  212.                         Ds1302Write(0x80,0);     //向秒寄存器寫入0
  213.                         Ds1302Write(0x8E,0x80);         //打開1302寫保護(hù)
  214.                   }
  215.      }
  216.          if(keyshi == 0)                                //“時”增加按鍵
  217.          {
  218.                  delay();
  219.                 if((keyshi==1)&&(keysetflag==1)) //判斷KEYSET標(biāo)志位,只有KEYSET按下后才運行
  220.                 {                        
  221.                         h1++;                                                 //小時加1,24小時制
  222.                         if(h1>23)
  223.                         {
  224.                                 h1 = 0;
  225.                         }
  226.                         DisplayData[0] = smgduan[h1/10];  //十進(jìn)制轉(zhuǎn)換送LED十位顯示
  227.                         DisplayData[1] = smgduan[h1%10];  //十進(jìn)制轉(zhuǎn)換送LED個位顯示
  228.                         hour = (h1/10*16)+(h1%10);         //將H1的值轉(zhuǎn)換成BCD碼賦給HOUR
  229.                         Ds1302Write(0x8E,0X00);                //關(guān)閉1302寫保護(hù)
  230.                         Ds1302Write(0x84,hour);          //向1302“時”寄存器寫入小時值
  231.                         Ds1302Write(0x8E,0x80);         //打開1302寫保護(hù)
  232.                 }
  233.          }
  234.          if(keyfen == 0)                          //“分”增加鍵
  235.          {
  236.                  delay();
  237.                 if((keyfen==1)&&(keysetflag==1))   //判斷KEYSET標(biāo)志位,只有KEYSET按下后才運行
  238.                 {        
  239.                         m1++;
  240.                         if(m1>59)                                   //分,十進(jìn)制
  241.                         {
  242.                                 m1 = 0;
  243.                         }
  244.                         DisplayData[2] = smgduan[m1/10];         //十進(jìn)制轉(zhuǎn)換送LED十位顯示
  245.                         DisplayData[3] = smgduan[m1%10];        //十進(jìn)制轉(zhuǎn)換送LED個位顯示
  246.                         min = (m1/10*16)+(m1%10);                //將m1的值轉(zhuǎn)換成BCD碼賦給min
  247.                         Ds1302Write(0x8E,0X00);                    //關(guān)閉寫保護(hù)
  248.                         Ds1302Write(0x82,min);              //向"分"寄存器寫入分鐘值
  249.                         Ds1302Write(0x8E,0x80);                    //打開寫保護(hù)
  250.                 }
  251.          }
  252.          if(keyBPC == 0)          //按鍵強制開啟BPC
  253.          {
  254.                  delay();
  255.                 if(keyBPC == 1)
  256.                 {
  257.                         keyBPCnum++;
  258.                         if(keyBPCnum == 1)         //按下一次,開啟BPC
  259.                         {
  260.                           BPC_EN = 0;
  261.                           BPC_FailLED = 1;
  262.                           keyBPCflag = 1;
  263.                     }
  264.                         if(keyBPCnum >= 2)          //按下第二次,關(guān)閉BPC
  265.                         {
  266.                           keyBPCnum = 0;
  267.                           BPC_EN = 1;
  268.                           BPC_FailLED = 0;
  269.                           keyBPCflag = 0;        
  270.                         }
  271.                 }               
  272.          }
  273. }

  274. /*********************************************
  275. * 整點報時函數(shù)     :AlarmRing()
  276. * 函數(shù)功能         : 整點報時

  277. **********************************************/
  278. void AlarmRing()
  279. {
  280.         uchar p,q;
  281.         p = (TIME[1]>>4)*10+(TIME[1]&0x0f)%10;        //讀取1302 變?yōu)槭M(jìn)制,分鐘為00
  282.         q = (TIME[0]>>4)*10+(TIME[0]&0x0f)%10;        //秒鐘為00
  283.         if((p|q) == 0) //分與秒相或為0時
  284.         {        
  285.                 if(alarmflag == 1)         //先判斷報時標(biāo)志打開,禁止報時段標(biāo)志為0
  286.                 {
  287.                   Ring = 1;                          //觸發(fā)報時
  288.                   delay();
  289.                   delay();
  290.                   Ring = 0;                          //關(guān)閉觸發(fā)
  291.             }        
  292.     }        
  293. }
  294. /************************************************************
  295. * 整點報時設(shè)定函數(shù) : Closealarm()
  296. **函數(shù)功能         : 設(shè)置整點報時時段

  297. ***********************************************************/
  298. void Closealarm()
  299. {
  300.         uchar k;
  301.         k = (TIME[2]>>4)*10+(TIME[2]&0x0f)%10;         //讀1302小時值,轉(zhuǎn)成十進(jìn)制,設(shè)定關(guān)閉鬧鐘時間段
  302.         if((0<=k)&&(k<=5))         //小5點,大于0點時段,關(guān)閉整點報時
  303.         {
  304.                 alarmflag = 0;        //關(guān)閉報時標(biāo)志 0-6點
  305.                 //alarmLED = 0;        //關(guān)閉報時指示燈
  306.         }
  307.         else                                //打開報時
  308.         {
  309.                 alarmflag = 1;          //否則打啟報時標(biāo)志位
  310.                 //alarmLED = 1;
  311.         }
  312. }
  313. /******************************************************
  314. * BPC接收函數(shù)    : recieveBPCtime()
  315. * 函數(shù)功能       : 接收BPC授時和寫入DS1302時間

  316. *******************************************************/
  317. void recieveBPCtime()
  318. {   
  319.     if(As_time)         //正確接收19位數(shù)據(jù)標(biāo)志位
  320.      {
  321.            As_time=0;        //清零標(biāo)志,并判斷一分鐘內(nèi)3列19組相同的數(shù)據(jù),“分時周月年”
  322.            if(
  323.                      (BPC_dat[0][1]==BPC_dat[1][1])&&(BPC_dat[0][1]==BPC_dat[2][1])
  324.                    &&(BPC_dat[0][2]==BPC_dat[1][2])&&(BPC_dat[0][2]==BPC_dat[2][2])
  325.                    &&(BPC_dat[0][3]==BPC_dat[1][3])&&(BPC_dat[0][3]==BPC_dat[2][3])
  326.                    &&(BPC_dat[0][4]==BPC_dat[1][4])&&(BPC_dat[0][4]==BPC_dat[2][4])
  327.                    &&(BPC_dat[0][5]==BPC_dat[1][5])&&(BPC_dat[0][5]==BPC_dat[2][5])
  328.                    &&(BPC_dat[0][6]==BPC_dat[1][6])&&(BPC_dat[0][6]==BPC_dat[2][6])
  329.                    &&(BPC_dat[0][7]==BPC_dat[1][7])&&(BPC_dat[0][7]==BPC_dat[2][7])
  330.                    &&(BPC_dat[0][8]==BPC_dat[1][8])&&(BPC_dat[0][8]==BPC_dat[2][8])
  331.                    &&(BPC_dat[0][10]==BPC_dat[1][10])&&(BPC_dat[0][10]==BPC_dat[2][10])
  332.                    &&(BPC_dat[0][11]==BPC_dat[1][11])&&(BPC_dat[0][11]==BPC_dat[2][11])
  333.                    &&(BPC_dat[0][12]==BPC_dat[1][12])&&(BPC_dat[0][12]==BPC_dat[2][12])
  334.                    &&(BPC_dat[0][13]==BPC_dat[1][13])&&(BPC_dat[0][13]==BPC_dat[2][13])
  335.                    &&(BPC_dat[0][14]==BPC_dat[1][14])&&(BPC_dat[0][14]==BPC_dat[2][14])
  336.                    &&(BPC_dat[0][15]==BPC_dat[1][15])&&(BPC_dat[0][15]==BPC_dat[2][15])
  337.                    &&(BPC_dat[0][16]==BPC_dat[1][16])&&(BPC_dat[0][16]==BPC_dat[2][16])
  338.                    &&(BPC_dat[0][17]==BPC_dat[1][17])&&(BPC_dat[0][17]==BPC_dat[2][17])
  339.              )
  340.                          Get_time=1;
  341.              }
  342.            if(Get_time)         //收到3幀相同的數(shù)據(jù)后,對Times[]數(shù)據(jù)賦值授時
  343.              {
  344.                    Get_time=0;                                   //標(biāo)志位清零
  345.                                    keysetflag = 1;                            //利用該標(biāo)志位來暫停讀DS1302
  346.                                    Times[0]=((BPC_dat[0][2]*4)+(BPC_dat[0][3]));  //BPC”時“,4進(jìn)制,第2、3位
  347.                    Times[1]=((BPC_dat[0][4]*16)+(BPC_dat[0][5]*4)+(BPC_dat[0][6])+1); //BPC”分“,4進(jìn)制,第4,5,6位,3幀數(shù)據(jù)相同后,分的起始點為第2分鐘00秒,要加1補償                                                   
  348.                                    Times[2]=(BPC_dat[0][9]);   //判斷BPC第10位識別上/下午,0,1為上午,2,3為下午
  349.                                    if(Times[2]<2)                   //上下午判斷,如果小于2,為上午
  350.                                      {
  351.                                                  hour = (Times[0]/10*16)+(Times[0]%10);          //時轉(zhuǎn)換成BCD
  352.                                                 min = (Times[1]/10*16)+(Times[1]%10);          //分轉(zhuǎn)換成BCD
  353.                                          }
  354.                                         else                         //上下午判斷,如果大于1,為下午
  355.                                          {
  356.                                                  hour = ((Times[0]+12)/10*16)+((Times[0]+12)%10);  //BPC下午,Times[3]要加12變?yōu)?4小時制并轉(zhuǎn)換為BCD
  357.                                                 min = (Times[1]/10*16)+(Times[1]%10);                  //分轉(zhuǎn)成BCD
  358.                                          }                                   
  359.                                            Ds1302Write(0x8E,0X00);          //關(guān)閉寫保護(hù)
  360.                                         Ds1302Write(0x84,hour);          //向時寄存器寫入小時值
  361.                                         Ds1302Write(0x82,min);    //向分寄存器寫入
  362.                                         Ds1302Write(0x80,0);      //向秒寄存器寫入0,一分鐘3幀相同信號,分加1后,秒歸0.無需判斷
  363.                                         Ds1302Write(0x8E,0x80);          //打開寫保護(hù)
  364.                                         keysetflag = 0;                          //恢復(fù)讀1302
  365.                                         BPC_ok = 0;                          //授時成功標(biāo)志清零
  366.                                         BPC_EN = 1;               //接收成功后,關(guān)閉BPC
  367.                                         BPC_FailLED = 0;          //關(guān)閉授時失敗指示燈
  368.                                         keyBPCflag = 0;                          //取消強制對時標(biāo)志位
  369.               }
  370. }
  371. /**************************************************
  372. * BPC自動接收函數(shù)  : BPC_openset()
  373. * 函數(shù)功能         : 設(shè)置BPC開啟授時時間

  374. *************************************************/
  375. void BPC_openset()
  376. {
  377.         uchar t;
  378.         t = (TIME[2]>>4)*10+(TIME[2]&0x0f)%10; //先讀出1302的小時值,轉(zhuǎn)換成十進(jìn)制
  379.         if(t == 2)                                  //夜間2點,持續(xù)接收BPC。
  380.         {
  381.                 if(BPC_ok)                        //先判斷BPC授時成功標(biāo)志位,授時成功一次,不再執(zhí)行該程序
  382.                 {
  383.                         BPC_EN = 0;                       //打開BPC授時模塊
  384.                         BPC_FailLED = 1;           //打開授時失敗指示燈
  385.                  }
  386.         }
  387.         if(t == 3)                              //夜時3點,如未成功授時自動關(guān)閉BPC
  388.         {
  389.                 if(keyBPCflag == 0)                  //判斷按鍵強制對時按鍵標(biāo)志位,如果有按鍵強制對時,不執(zhí)行
  390.             {
  391.                    BPC_EN = 1;                  //1小時內(nèi)授時不成功,關(guān)閉BPC模塊,不關(guān)指示燈用于提示授時失敗
  392.                    BPC_ok = 1;            // 開授時成功標(biāo)志位,以便下一個2點能開啟BPC模塊
  393.              }
  394.         }        
  395. }

  396. /*******************************************************************************
  397. * 函 數(shù) 名       : main
  398. * 函數(shù)功能                 : 主函數(shù)

  399. *******************************************************************************/
  400. void main()
  401. {        
  402.         Ring = 0;                         // 整點報時初始值
  403.         BPC_EN = 1;                          //BPC使能初始
  404.         BPC_FailLED = 0;          //授時失敗指示燈初始

  405.         EA = 1;
  406.         TMOD = 0x01;                //T0
  407.         TH0 = (65536-2000)/256;           //LED刷新和定時讀DS1302
  408.         TL0 = (65536-2000)%256;
  409.         TR0 = 1;
  410.         ET0 = 1;

  411.         IT1=1;        //P33下降沿觸發(fā)
  412.     EX1=1;                  //開啟外部中斷
  413.     PX1=1;                  //外部中斷優(yōu)先

  414.     //Ds1302Init(); //本程序無需初始化DS1302

  415.         while(1)
  416.         {
  417.                 Closealarm();       //整點報時關(guān)閉時段
  418.                 keyscan();                //按鍵
  419.                 AlarmRing();        //整點報時
  420.                 BPC_openset();            // BPC開啟函數(shù)
  421.                 recieveBPCtime();   //BPC接收轉(zhuǎn)換函數(shù)
  422.                
  423.                 if(flag200ms)                  //讀1302時間標(biāo)志
  424.                 {
  425.                         flag200ms = 0;
  426.                         if(keysetflag == 0)         //有按鍵調(diào)整時,標(biāo)志位置1,暫停讀1302
  427.                         {
  428.                           datapros();             //數(shù)據(jù)處理函數(shù)        
  429.                     }        
  430.         }
  431.         }        
  432. }               

  433. /*******************************************************************************
  434. * 函 數(shù) 名       : interruptimer()
  435. * 函數(shù)功能                 : 中斷,刷新數(shù)碼管,BPC時間記時判斷脈寬值

  436. *******************************************************************************/
  437. void interrutptimer() interrupt 1
  438. {
  439.         uchar i,ms;
  440.         TH0 = (65536-2000)/256;           //1ms
  441.         TL0 = (65536-2000)%256;
  442.         ms++;
  443.         if(ms>=200)
  444.         {
  445.                 ms = 0;
  446.                 flag200ms = 1;                 //讀1302間隔時間段
  447.         }
  448.         switch(i)
  449.         {
  450.                 case 0:        P1=0x3e;i++;P0=0x00;P0=DisplayData[5];break;         // 秒
  451.                 case 1:        P1=0x3d;i++;P0=0x00;P0=DisplayData[4];break;
  452.                 case 2:        P1=0x3b;i++;P0=0x00;P0=DisplayData[3];break;         //分
  453.                 case 3:        P1=0x37;i++;P0=0x00;P0=DisplayData[2];break;
  454.                 case 4:        P1=0x2f;i++;P0=0x00;P0=DisplayData[1];break;         //時
  455.                 case 5:        P1=0x1f;i=0;P0=0x00;P0=DisplayData[0];break;        
  456.                 default: break;
  457.         }
  458.         
  459.   Dat_add++;                     //外部中斷內(nèi)對ADD清零,1500次內(nèi),有外部中斷,重新清零
  460.   if(Dat_add>1500)     //BPC啟始信號,每1MS對DAT_add加1,如在1500個周期內(nèi)沒有進(jìn)入外部中斷被清零,1.5S后標(biāo)志找到超始信號,重新對Dat_num清零,以便重新對19個位賦值
  461.           Dat_num=0;               //對數(shù)組清零,說明已授收到超始脈沖

  462.   if(BPC_add)          //外部中斷標(biāo)志為真
  463.     {
  464.       if(!BPC)                // 第1個脈沖負(fù)邊到來時
  465.                   BPC_temp++;           //用BPC_temp累加值來判斷脈寬
  466.      else
  467.         {
  468.           BPC_add=0;   //當(dāng)?shù)?個脈沖跳變?yōu)檎厱r,對BPC_add標(biāo)志位清零,等待下個脈沖的中斷
  469.           if((BPC_temp>50)&&(BPC_temp<150)) BPC_dat[Dat_su][Dat_num]=0;        //判斷脈寬值,賦值給二維數(shù)組的第[0][0]
  470.      else if((BPC_temp>150)&&(BPC_temp<250))BPC_dat[Dat_su][Dat_num]=1;
  471.      else if((BPC_temp>250)&&(BPC_temp<350))BPC_dat[Dat_su][Dat_num]=2;
  472.      else if((BPC_temp>350)&&(BPC_temp<450))BPC_dat[Dat_su][Dat_num]=3;
  473.      else Dat_num=0;    //如果以上有不正確的值,對Dat_num清零重來
  474.          
  475.           Dat_num++;      //對第二維的數(shù)據(jù)的值清零
  476.           if(Dat_num>18)
  477.             {
  478.               Dat_num=0;
  479.               As_time=1;    //正確接收19位數(shù)據(jù)標(biāo)志位
  480.               Dat_su++;                //對第一維的數(shù)據(jù)增加,最終共3*19組數(shù)據(jù)
  481.                           if(Dat_su>2)
  482.                           Dat_su=0;
  483.             }
  484.            BPC_temp=0;            //脈沖累加值清零
  485.         }
  486.      }        
  487. }

  488. /***********************************************************************
  489. * 電波鐘中斷檢測函數(shù)    :Time_EX1()
  490. * 函數(shù)功能              : BPC當(dāng)外部下降沿時產(chǎn)生中斷,標(biāo)志置位,清零時間累加值

  491. ***************************************************************************/
  492. void Time_EX1(void)interrupt 2          //外部中斷,優(yōu)先級為最高,防止漏檢
  493. {
  494.   BPC_add=1;                                          //外部中斷標(biāo)志
  495.   Dat_add=0;                                          //1ms定時中斷內(nèi)對變量加1,用來判斷1.5S的超始脈沖
  496. }

復(fù)制代碼
發(fā)貼不易,敬請評論指點,特別是在程序上,希望能學(xué)習(xí)時步。
全部資料51hei下載地址:
大笨鐘.zip (53.95 KB, 下載次數(shù): 167)

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2020-6-20 17:03 | 顯示全部樓層
安裝時需要注意,電波鐘模塊要離單片機遠(yuǎn)些,天線也要遠(yuǎn)離數(shù)碼管,之所以選這么大的盒子,就是為了解決空間物理距離問題。
回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2020-6-20 18:00 | 顯示全部樓層
通過得這么快,管理員辛苦了
回復(fù)

使用道具 舉報

ID:392521 發(fā)表于 2020-6-22 08:54 | 顯示全部樓層
感謝分享,我也打算做一個玩,請問樓主有沒有原理圖?

回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2020-6-22 20:17 | 顯示全部樓層
sdqzlihui 發(fā)表于 2020-6-22 08:54
感謝分享,我也打算做一個玩,請問樓主有沒有原理圖?

原理圖沒畫,硬件都是現(xiàn)成的,對應(yīng)連好就行,更改端口定義就行。需要注意的是BPC電波鐘信號要加一個NPN倒相輸入,它的供電要加一個3.3V的LDO, 單片機的BPC_EN控制腳,采用電阻為壓將這個IO口變?yōu)?V,其它的就是照常規(guī)連接就好。
在這幾天的不斷試驗中發(fā)現(xiàn),采用STC1T的單片機,加上又采用了24MHZ的晶振,重復(fù)開關(guān)機,會使時間讀出錯誤碼,1302反應(yīng)不過來,單片機太快,自己讀到自己的IO口電平了,讀出92點35分,所以建議采用8MHZ晶振,給1302足夠的反應(yīng)時間。通過更改后就正常了。
回復(fù)

使用道具 舉報

ID:143244 發(fā)表于 2020-6-23 21:07 | 顯示全部樓層
動手做,記得住,不過用便宜點的開發(fā)板更好!
回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2020-11-13 14:09 來自手機 | 顯示全部樓層
近幾天又重新做了個2.0版本來除了但留之前的功能外,還增加了夜間關(guān)閉led的功能,然后通過聲控喚醒10秒,一來省電,二來放臥室不會影響到睡覺,完全是個小夜燈。
回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2020-11-13 14:10 來自手機 | 顯示全部樓層
增加了日期和星期,溫濕度等功能。
IMG_20201113_140607.jpg
回復(fù)

使用道具 舉報

ID:846386 發(fā)表于 2020-12-2 23:51 | 顯示全部樓層
樓主把最新的電路圖和代碼發(fā)上來學(xué)習(xí),謝謝
回復(fù)

使用道具 舉報

ID:383885 發(fā)表于 2020-12-3 10:33 | 顯示全部樓層
太棒了,牛!
回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2020-12-9 11:58 來自手機 | 顯示全部樓層
kiccleaf 發(fā)表于 2020-12-2 23:51
樓主把最新的電路圖和代碼發(fā)上來學(xué)習(xí),謝謝

哪天有空用電腦上傳上來
回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2022-4-17 07:31 來自手機 | 顯示全部樓層
利用一個爛石英鐘外殼,打印一張梅花圖裝飾,又做了個辦工桌小鬧鐘。十分具有年代感。
IMG_20220417_072832.jpg
回復(fù)

使用道具 舉報

ID:430492 發(fā)表于 2022-4-17 13:30 | 顯示全部樓層
樓上這張圖,想法不錯,很好看!
回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2022-4-17 14:07 來自手機 | 顯示全部樓層
cooleaf 發(fā)表于 2022-4-17 13:30
樓上這張圖,想法不錯,很好看!!

謝謝,業(yè)余時間,迷上了各種diy。做的東西挺多。純屬娛樂。
回復(fù)

使用道具 舉報

ID:478849 發(fā)表于 2022-4-29 09:08 | 顯示全部樓層
謝謝分享,學(xué)習(xí)了,原理圖是怎么接線的
回復(fù)

使用道具 舉報

ID:146324 發(fā)表于 2022-5-5 11:11 | 顯示全部樓層
樓主,能簡單的畫個電路圖嗎?不知道怎么接線。謝謝了
回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2022-5-5 11:27 來自手機 | 顯示全部樓層
突然想學(xué)習(xí) 發(fā)表于 2022-5-5 11:11
樓主,能簡單的畫個電路圖嗎?不知道怎么接線。謝謝了

其它的按鍵,顯示等,根據(jù)自己的喜好使用,都是通用的。我畫了電波模塊的接線方法,可參考。
IMG_20220505_112454.jpg
回復(fù)

使用道具 舉報

ID:1011444 發(fā)表于 2022-5-8 18:23 | 顯示全部樓層
請教:程序編譯未通過,提示未發(fā)現(xiàn)設(shè)備,需要更新設(shè)備,這是什么原因?另外換用其他單片機(比如stc89c52rc)行嗎、
回復(fù)

使用道具 舉報

ID:744744 發(fā)表于 2022-5-8 22:22 來自手機 | 顯示全部樓層
kz0018 發(fā)表于 2022-5-8 18:23
請教:程序編譯未通過,提示未發(fā)現(xiàn)設(shè)備,需要更新設(shè)備,這是什么原因?另外換用其他單片機(比如stc89c ...

至于是什么問題導(dǎo)致編輯不通過,從描述是很難找出原因的。單片機可以換,不影響。
回復(fù)

使用道具 舉報

ID:383222 發(fā)表于 2022-5-18 12:33 | 顯示全部樓層
可以通過編譯,謝謝,分享,
回復(fù)

使用道具 舉報

ID:272411 發(fā)表于 2023-4-19 21:28 | 顯示全部樓層
下載收藏,謝謝分享?梢酝ㄟ^編譯
回復(fù)

使用道具 舉報

ID:138707 發(fā)表于 2023-8-6 17:01 | 顯示全部樓層
樓上這張圖,想法不錯,很好看。
回復(fù)

使用道具 舉報

ID:1085441 發(fā)表于 2023-8-7 02:06 | 顯示全部樓層
可以問一下電波鐘模塊的型號,價格多少?
回復(fù)

使用道具 舉報

ID:88256 發(fā)表于 2023-8-7 09:59 | 顯示全部樓層
電波鐘在很多地方的室內(nèi)都不太好接收吧?樓主做的是實用性的東西,我覺得可以換個方案,現(xiàn)在的家里WIFI都是一直開著的,可以使用ESP-12F模塊作為主控以及網(wǎng)絡(luò)連接,用網(wǎng)絡(luò)對時,走時靠模塊,有糾結(jié)的話上RTC(不斷電不斷網(wǎng)其實真沒必要);顯示用TM1650系列,可以7級調(diào)節(jié)亮度(配合光敏電阻自動調(diào)節(jié)也行),電源、阻容不算,也就使用ESP-12F+TM1650+數(shù)碼管,極度簡潔。
回復(fù)

使用道具 舉報

ID:195496 發(fā)表于 2023-8-11 08:56 | 顯示全部樓層
kz0018 發(fā)表于 2022-5-8 18:23
請教:程序編譯未通過,提示未發(fā)現(xiàn)設(shè)備,需要更新設(shè)備,這是什么原因?另外換用其他單片機(比如stc89c ...

要更改頭文件
回復(fù)

使用道具 舉報

ID:929517 發(fā)表于 2023-9-11 18:17 來自手機 | 顯示全部樓層
不是低電平才能點亮LED嗎,你這個怎么是高電平?另外,按鍵怎么沒有消抖?
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表