找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

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

學(xué)習(xí)單片機(jī),制作了一臺(tái)LED電子鐘

  [復(fù)制鏈接]
ID:97023 發(fā)表于 2020-3-31 00:39 | 顯示全部樓層 |閱讀模式
  學(xué)習(xí)單片機(jī)一段時(shí)間了,一直想做一個(gè)東西來(lái)驗(yàn)證一下自己的學(xué)習(xí)效果,“流水燈”之類覺得太簡(jiǎn)單;“示波器”、“掃頻儀”、“LCR”、“晶體管特性曲線儀”等儀器又覺得太難,自己覺得還是制作一個(gè)電子鐘難度比較適中。
  只所以選擇制作LED顯示的電子鐘,是因?yàn)槿ツ暝诰W(wǎng)上30元買得有96只1寸的LED數(shù)碼管,總得把它們消化點(diǎn)才是。當(dāng)然成功后我還會(huì)再制作LCD顯示的電子鐘,那是后話。
  原本想用14個(gè)LED數(shù)碼管來(lái)制作這個(gè)電子鐘,讓它直接顯示:年、月、日、時(shí)、分、秒,其中“年”用4位,免得再出現(xiàn)當(dāng)年“千年蟲”的問(wèn)題,其它通通用兩位,當(dāng)然還可以多加一位用來(lái)顯示“星期”。但這樣一來(lái),這個(gè)電子鐘就顯得太寬了,做出來(lái)有點(diǎn)龐大。
  最后還是決定按照傳統(tǒng)方法,用6位LED數(shù)碼管就行了,用一個(gè)按鍵來(lái)切換日期與時(shí)間的顯示。
  根據(jù)以上想法設(shè)計(jì)的電路原理圖:
00 電路原理圖.png


  要讓鐘走起來(lái)不難,網(wǎng)上有很多現(xiàn)成的代碼,關(guān)鍵的難點(diǎn)是時(shí)鐘的設(shè)置(調(diào)整)。
  我希望在進(jìn)入設(shè)置狀態(tài)時(shí),對(duì)應(yīng)的LED應(yīng)該能夠閃爍,以提醒我當(dāng)前設(shè)置的是年、月、日、時(shí)、分、秒的哪一位(其實(shí)都是兩位)?
  由于每位LED數(shù)碼管都采用動(dòng)態(tài)顯示,在動(dòng)態(tài)顯示時(shí)又如何使某兩位閃爍,一下子沒(méi)想通怎么做。
  參考了很多網(wǎng)上的資料以及翻了很多書籍,都沒(méi)發(fā)現(xiàn)哪一款LED數(shù)碼管的電子鐘在設(shè)置時(shí)間或日期時(shí),對(duì)應(yīng)的LED數(shù)碼管能夠閃爍,也許是我沒(méi)有看懂別人的代碼。
  想了幾天后終于想到了一個(gè)辦法:我們知道,LED數(shù)碼管的動(dòng)態(tài)顯示,無(wú)非就是在某一個(gè)時(shí)刻只讓一只LED數(shù)碼管亮,其余的LED數(shù)碼管是不亮的,下一個(gè)時(shí)刻才讓下一位LED數(shù)碼管亮,循環(huán)往復(fù),只要時(shí)間足夠快,由于人眼的“視覺暫留”作用,我們看到所有的LED數(shù)碼管都是亮著的。
  我的辦法就是:需要閃爍的這兩位LED數(shù)碼管,當(dāng)輪到它們亮?xí)r暫時(shí)不亮,將亮的機(jī)會(huì)讓給其它的數(shù)碼管,這就使得它們“滅”的時(shí)間長(zhǎng)一點(diǎn),能讓眼睛感覺到;輪到它們亮?xí)r,就讓它們循環(huán)多亮一段時(shí)間,它們循環(huán)結(jié)束以后才將亮的機(jī)會(huì)交給其它的數(shù)碼管。這樣的效果,通過(guò)眼睛看到,這兩位數(shù)碼管一滅一亮地閃爍起來(lái)了。實(shí)際情況下,其它數(shù)碼管也有輕微的閃爍,但沒(méi)有這兩位明顯,眼睛不容易觀察到。
  我就通過(guò)這個(gè)伎倆用來(lái)欺騙眼睛。
  由于機(jī)器配置有點(diǎn)低,所以這個(gè)效果用Proteus仿真不出來(lái),只有用面包板實(shí)際搭電路才行。
  我通過(guò)測(cè)試,閃爍的數(shù)碼管“亮”時(shí),循環(huán)4次就夠了,次數(shù)多了,其它數(shù)碼管就會(huì)跟著閃爍起來(lái);次數(shù)少了閃爍又不明顯。
  說(shuō)這么多,只是思路,具體實(shí)現(xiàn)看源代碼。
  結(jié)構(gòu)上,采用了4個(gè)按紐開關(guān)進(jìn)行控制:
  1、【設(shè)置/移動(dòng)/退出】;
  2、【加】;
  3、【減】;
  4、【確定/翻頁(yè)】。
  各按紐功能解說(shuō):
  【設(shè)置/移動(dòng)/退出】按紐的功能:
  單擊第①次,進(jìn)入(設(shè)置),第一位(其實(shí)是兩個(gè)數(shù)碼管,下同)閃爍;
  單擊第②次,第二位閃爍;
  單擊第③次,第三位閃爍;
  單擊第④次,下一頁(yè)第一位閃爍;
  單擊第⑤次,下一頁(yè)第二位閃爍;
  單擊第⑥次,下一頁(yè)第三位閃爍;
  單擊第⑦次,退出(設(shè)置),進(jìn)入走時(shí)狀態(tài)。
  【加】、【減】:只在設(shè)置狀態(tài)有效;
  【確定/翻頁(yè)】:在設(shè)置狀態(tài)下,保存并退出設(shè)置;在走時(shí)狀態(tài)下,切換日期和時(shí)間。
  用面包板搭建的功能驗(yàn)證電路證實(shí)了上述想法。
01 面包板驗(yàn)證電路.jpg


  在面包板上成功以后,開始成品制作。
  電子鐘由三個(gè)模塊組成:顯示板、控制板和電源板。
  顯示板由6個(gè)LED數(shù)碼管組成,用一塊9×15CM的洞洞板裁成兩塊拼接而成,為了使兩塊洞洞板保持在一個(gè)平面,在它們的后面又加了一塊裝修吊頂用的“輕鋼龍骨”作為支撐:
IMG_20190618_095136.jpg

IMG_20190618_095153.jpg

  為了避免焊接錯(cuò)誤,數(shù)碼管相同的段用相同顏色的導(dǎo)線連接。
IMG_20190621_230816.jpg


IMG_20190622_004009.jpg


  七個(gè)段由這七個(gè)插針輸出
IMG_20190622_004128.jpg


  每一位數(shù)碼管的控制由一塊單獨(dú)的控制板完成,這塊控制板固定在數(shù)碼管背面的“輕鋼龍骨”上,它們構(gòu)成了完整的顯示模塊,通過(guò)插針與單片機(jī)主控板連接。
IMG_20190622_095018.jpg


IMG_20190622_103105.jpg

  單片機(jī)模塊:
IMG_20190623_213313.jpg


IMG_20190623_213417.jpg

  因?yàn)殡娫词?2V的,所以用7805將電壓控制在5V:
IMG_20190623_213911.jpg


  電源模塊采用成品12V/1A開關(guān)電源,這種電源在網(wǎng)上1.50元一只(輸出線被剪掉的),我買得有幾十只,另外家人多年來(lái)丟棄的各種電源,都被我收集了起來(lái),也有幾十只,不管做什么電子裝置,我都能找到合適的電源。
IMG_20200331_001052.jpg


  各個(gè)模塊連接起來(lái)工作正常了:
IMG_20190624_170212.jpg


  日期顯示:
IMG_20190626_001444.jpg


  時(shí)間顯示:
IMG_20190626_001501.jpg


  用撿來(lái)的層板制作外殼:
IMG_20190702_113343.jpg


IMG_20190704_082007.jpg

  外殼全部用白乳膠粘接,沒(méi)用一顆釘子。
IMG_20190705_084345.jpg


IMG_20190706_162320.jpg

IMG_20190707_133204.jpg


IMG_20190708_233139.jpg

  貼上黑胡桃木的貼皮美化一下:
IMG_20190720_142536.jpg

  內(nèi)部布局:
IMG_20190720_142543.jpg

  開關(guān)電源的PCB板很小,不好單獨(dú)固定,我是將電源外殼鋸掉一部分,利用它內(nèi)部的卡槽來(lái)固定電源。
IMG_20190720_142618.jpg

  右下角那片軟包裝鋰電池是3.7V/180mAh的,在不使用電子鐘時(shí)給DS1302供電,以免丟失設(shè)置好的時(shí)間。
IMG_20190720_142626.jpg


IMG_20190720_142738.jpg
  后蓋板的螺絲孔與里面的螺帽對(duì)得很正,我是怎么做到的?給大家分享一點(diǎn)經(jīng)驗(yàn):先在后蓋板適當(dāng)位置鉆孔,這時(shí)只需注意孔的中心與左右邊緣的距離等于螺帽的半徑,也就是說(shuō),螺帽應(yīng)該緊貼著側(cè)面板外沿,這個(gè)可以用尺子測(cè)量畫線再鉆孔;然后將4顆螺絲與螺帽固定在后蓋板上,在前面板還空著的情況下,將后蓋板小心地在后邊推到位,用一根長(zhǎng)一點(diǎn)的竹簽粘少許兌好的AB膠,從前面窗口伸進(jìn)去,將它們涂到螺帽與側(cè)面板之間,這時(shí)不需要涂多少,只要能將它們粘住就行,等幾個(gè)小時(shí)AB膠固化后,再將后蓋板及螺絲一同拆下來(lái),這時(shí)螺帽就已經(jīng)粘在側(cè)面板上了。再次兌一些AB膠,將螺帽與側(cè)面板膠水不足的地方補(bǔ)足即可。
  如果你有更好的方法,就當(dāng)我沒(méi)說(shuō)。
  薄膜開關(guān)的功能定義:
薄膜開關(guān).png


IMG_20200328_221527.jpg

原理圖及代碼:
LED數(shù)碼管電子鐘.rar (60.08 KB, 下載次數(shù): 144)
為了節(jié)約大家的黑幣,所有文件壓縮在一塊。





評(píng)分

參與人數(shù) 2黑幣 +60 收起 理由
王朗的誘惑 + 10 優(yōu)雅
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:328014 發(fā)表于 2020-3-31 01:06 | 顯示全部樓層
好東東啊 下面是樓主的主程序:
  1. /*******************************************************
  2. 功能:LED數(shù)碼管電子鐘
  3. *******************************************************/
  4. #include <reg52.h>
  5. #include <intrins.h>

  6. #define uchar unsigned char
  7. #define uint unsigned int

  8. //函數(shù)定義
  9. void DelayMS(uint x);                                                //延時(shí) xms(晶振:11.0592MHz,)
  10. uchar Get_A_Byte_FROM_DS1302();                                //從DS1302讀取一個(gè)字節(jié)
  11. uchar Read_Data( uchar addr );                                //從DS1302指定位置讀數(shù)據(jù)
  12. void Write_A_Byte_TO_DS1302( uchar x );                //向DS1302寫入一個(gè)字節(jié)
  13. void Write_DS1302( uchar addr, uchar dat );        //向DS1302某地址寫數(shù)據(jù)
  14. void SET_DS1302();                                                        //設(shè)置日期時(shí)間
  15. void GetTime();                                                                //讀取當(dāng)前時(shí)間日期
  16. void LedDisplay();                                                        //顯示數(shù)據(jù)
  17. void Scan_Key();                                                        //掃描鍵盤
  18. void Init();                                                                //系統(tǒng)初始化
  19. void Play();                                                                //蜂鳴器發(fā)音
  20. void Format_DS1302();                                                //日期格式化

  21. sbit RST = P3^5;                        //DS1302復(fù)位線
  22. sbit SDA = P3^6;                        //DS1302數(shù)據(jù)線
  23. sbit CLK = P3^7;                        //DS1302時(shí)鐘線

  24. sbit NOT = P3^4;                        //日期分隔小數(shù)點(diǎn)和時(shí)間分隔冒號(hào)(1-冒號(hào)亮、0-小數(shù)點(diǎn)亮)

  25. sbit BEEP = P1^7;                        //蜂鳴器輸出端口

  26. uchar Current_Time[7];                //保存所讀取的日期時(shí)間(秒分時(shí)日月周年)
  27. uchar Display_Buffer[12];   //處理過(guò)的日期時(shí)間,用于數(shù)碼管顯示

  28. uchar DelayTwinkle = 5;                //閃爍延時(shí)長(zhǎng)度,原200
  29. uchar TimeTwinkle = 4;                //閃爍顯示時(shí)間,原30
  30. uchar WeiTwinkle = 0;                //閃爍的位
  31. uchar TimeShake = 100;                //去抖動(dòng)延時(shí)時(shí)間長(zhǎng)度

  32. uint BeepTime = 0;                //蜂鳴器響一次的間隔時(shí)間

  33. uint Set_State = 0;                        //0:走時(shí)狀態(tài)、1:設(shè)置狀態(tài)。
  34. bit DateTime_State = 0;                //0:顯示時(shí)間、1:顯示日期。
  35. uint Count = 0;                                //記錄“K_Setup”的狀態(tài)

  36. //按鍵定義
  37. sbit K_Setup        = P1^2;                //設(shè)置/移動(dòng)/退出
  38. sbit K_Add                = P1^3;                //加1
  39. sbit K_Sub                = P1^0;                //減1
  40. sbit K_OK                = P1^1;                //保存并退出/翻頁(yè)
  41. sbit K_GND                = P1^4;                //由于薄膜開關(guān)的原因,此腳定義為地。

  42. sbit K_FORMAT        = P1^5;                //格式化(使日期時(shí)間內(nèi)容為:2019-06-17 12:00:00)

  43. //共陽(yáng)LED數(shù)碼管位碼(從左到右:1、2、3、4、5、6)
  44. //用PNP管驅(qū)動(dòng)
  45. code uchar WEI_CODE [] =
  46. {
  47.         0xFE,                //1          11111110
  48.         0xFD,                //2          11111101
  49.         0xFB,                //3          11111011
  50.         0xF7,                //4          11110111
  51.         0xEF,                //5          11101111
  52.         0xDF                //6          11011111
  53. };

  54. //共陽(yáng)LED數(shù)碼管段碼
  55. code uchar DSY_CODE [] =
  56. {
  57.         0x40,                //0
  58.         0x79,                //1
  59.         0x24,                //2
  60.         0x30,                //3
  61.         0x19,                //4
  62.         0x12,                //5
  63.         0x02,                //6
  64.         0x78,                //7
  65.         0x00,                //8
  66.         0x10                //9
  67. };

  68. // 延時(shí) xms(晶振:11.0592MHz,)
  69. void DelayMS(uint x)
  70. {
  71.         uchar i;
  72.         while( x-- )
  73.         {
  74.                 for( i=0; i<111; i++ );
  75.         }
  76. }

  77. //蜂鳴器發(fā)音
  78. void Play()
  79. {
  80.         uchar i, j;
  81.         for( i = 0; i < 250; i++ )
  82.         {
  83.                 BEEP = ~BEEP;
  84.                 for (j = 0; j < 30; j++ )
  85.                 {
  86.                         _nop_();                //延時(shí)時(shí)間長(zhǎng)短決定發(fā)音頻率
  87.                 }
  88.         }
  89.         BEEP = 0;
  90. }                                                                                                           

  91. //從DS1302讀取一個(gè)字節(jié)
  92. uchar Get_A_Byte_FROM_DS1302()
  93. {
  94.         uchar i,b,t;
  95.         for ( i = 0; i < 8; i++ )
  96.         {
  97.                 b >>= 1;
  98.                 t = SDA;
  99.                 b |= t << 7;
  100.                 CLK = 1;
  101.                 CLK = 0;
  102.         }
  103.         //BCD碼轉(zhuǎn)換
  104.         return b / 16 * 10 + b % 16;
  105. }

  106. //從DS1302指定位置讀數(shù)據(jù)
  107. uchar Read_Data( uchar addr )
  108. {
  109.         uchar dat;
  110.         RST = 0;
  111.         CLK = 0;
  112.         RST = 1;
  113.         Write_A_Byte_TO_DS1302( addr );
  114.         dat = Get_A_Byte_FROM_DS1302();
  115.         CLK = 1;
  116.         RST = 0;
  117.         return dat;
  118. }

  119. //向DS1302寫入一個(gè)字節(jié)
  120. void Write_A_Byte_TO_DS1302( uchar x )
  121. {
  122.         uchar i;
  123.         for ( i = 0; i < 8; i++ )
  124.         {
  125.                 SDA = x & 1;
  126.                 CLK = 1;
  127.                 CLK = 0;
  128.                 x >>= 1;
  129.         }
  130. }

  131. //向DS1302某地址寫數(shù)據(jù)
  132. void Write_DS1302( uchar addr, uchar dat )
  133. {
  134.         CLK = 0;
  135.         RST = 1;
  136.         Write_A_Byte_TO_DS1302( addr );
  137.         Write_A_Byte_TO_DS1302( dat );
  138.         CLK = 0;
  139.         RST = 0;
  140. }

  141. //設(shè)置日期時(shí)間,括號(hào)里面是地址
  142. //秒(0x80)分(0x82)時(shí)(0x84)日(0x86)月(0x88)周(0x8a)年(0x8c)
  143. void SET_DS1302()
  144. {
  145.         uchar i;
  146.         Write_DS1302( 0x8E, 0x00 );        //寫控制字,取消寫保護(hù)
  147.         for ( i = 0; i < 7; i++ )
  148.         {
  149.                 Write_DS1302( 0x80 + 2 * i, ( Current_Time[i] / 10 << 4 ) | ( Current_Time[i] % 10 ) );
  150.         }
  151.         Write_DS1302( 0x8E, 0x80 );        //加保護(hù)
  152. }

  153. //日期格式化,使日期時(shí)間值為合法數(shù)據(jù)(使日期時(shí)間內(nèi)容為:2019-06-20 12:00:00)
  154. void Format_DS1302()
  155. {
  156.         Current_Time[0] = 0x00;                //秒
  157.         Current_Time[1] = 0x00;                //分
  158.         Current_Time[2] = 0x0C;                //12小時(shí)
  159.         Current_Time[3] = 0x14;                //20日
  160.         Current_Time[4] = 0x06;                //06月
  161.         Current_Time[5] = 0x05;                //周5(星期日是一周的開始)
  162.         Current_Time[6] = 0x13;                //19年
  163.         
  164.         SET_DS1302();
  165. }

  166. //讀取當(dāng)前時(shí)間日期(秒、分、時(shí)、日、月、周、年)
  167. //將讀取到的日期時(shí)間保存到顯示緩沖區(qū)中。
  168. //運(yùn)行時(shí)間約 2.4ms
  169. void GetTime()
  170. {
  171.         uchar i;
  172.         for ( i = 0; i < 7; i++ )
  173.         {
  174.                 Current_Time[i] = Read_Data( 0x81 + 2 * i );
  175.         }
  176.         Display_Buffer[0] = DSY_CODE[ Current_Time[2] / 10 ];           //小時(shí)的十位
  177.         Display_Buffer[1] = DSY_CODE[ Current_Time[2] % 10 ];           //小時(shí)的個(gè)位
  178.         Display_Buffer[2] = DSY_CODE[ Current_Time[1] / 10 ];           //分的十位
  179.         Display_Buffer[3] = DSY_CODE[ Current_Time[1] % 10 ];           //分的個(gè)位
  180.         Display_Buffer[4] = DSY_CODE[ Current_Time[0] / 10 ];           //秒的十位
  181.         Display_Buffer[5] = DSY_CODE[ Current_Time[0] % 10 ];           //秒的個(gè)位

  182.         Display_Buffer[6] = DSY_CODE[ Current_Time[6] / 10 ];           //年的十位
  183.         Display_Buffer[7] = DSY_CODE[ Current_Time[6] % 10 ];           //年的個(gè)位
  184.         Display_Buffer[8] = DSY_CODE[ Current_Time[4] / 10 ];           //月的十位
  185.         Display_Buffer[9] = DSY_CODE[ Current_Time[4] % 10 ];           //月的個(gè)位
  186.         Display_Buffer[10] = DSY_CODE[ Current_Time[3] / 10 ];           //日的十位
  187.         Display_Buffer[11] = DSY_CODE[ Current_Time[3] % 10 ];           //日的個(gè)位
  188.         Display_Buffer[12] = DSY_CODE[ Current_Time[5] - 1 ];           //周的個(gè)位(星期日是一周的開始)
  189. }

  190. //顯示數(shù)據(jù)(運(yùn)行時(shí)間約 12ms)
  191. void LedDisplay()
  192. {
  193.         uchar i;
  194.         if ( Set_State == 0 )                //走時(shí)狀態(tài)
  195.         {
  196.                 WeiTwinkle = 0;
  197.                 if ( DateTime_State == 0 )                        //顯示時(shí)間
  198.                 {
  199.                         NOT = 1;
  200.                         for ( i = 0; i < 6; i++ )
  201.                         {
  202.                                 P2 = WEI_CODE[ i ];
  203.                                 P0 = Display_Buffer[ i ];
  204.                                 DelayMS(1);
  205.                                 P2 = 0xFF;
  206.                                 P0 = 0xFF;
  207.                                 DelayMS(1);
  208.                         }
  209.                 }
  210.                 else                        //顯示日期
  211.                 {
  212.                         NOT = 0;
  213.                         for ( i = 0; i < 6; i++ )
  214.                         {
  215.                                 P2 = WEI_CODE[ i ];
  216.                                 P0 = Display_Buffer[ i + 6 ];
  217.                                 DelayMS(1);
  218.                                 P2 = 0xFF;
  219.                                 P0 = 0xFF;
  220.                                 DelayMS(1);
  221.                         }
  222.                 }
  223.         }
  224.         else                //設(shè)置狀態(tài)
  225.         {
  226.                 uchar j,k;
  227.                 if ( DateTime_State == 0 )                        //顯示時(shí)間
  228.                 {
  229.                         NOT = 1;
  230.                         for ( i = 0; i < 6; i++ )
  231.                         {
  232.                                 if ( i != WeiTwinkle &&  i != WeiTwinkle + 1 )         //不閃爍的位
  233.                                 {
  234.                                         P2 = WEI_CODE[ i ];
  235.                                         P0 = Display_Buffer[ i ];
  236.                                         DelayMS(1);
  237.                                 }
  238.                                 else if ( j > DelayTwinkle )   //閃爍的位(2位)
  239.                                 {
  240.                                         for ( k = 0; k < TimeTwinkle; k++ )
  241.                                         {
  242.                                                 P2 = WEI_CODE[ i ];
  243.                                                 P0 = Display_Buffer[ i ];
  244.                                                 DelayMS( 1 );
  245.                                                 P2 = WEI_CODE[ i + 1 ];
  246.                                                 P0 = Display_Buffer[ i + 1 ];
  247.                                                 DelayMS( 1 );
  248.                                         }
  249.                                         j = 0;
  250.                                 }
  251.                                 P2 = 0xFF;
  252.                                 P0 = 0xFF;
  253.                                 DelayMS(1);
  254.                                 j++;
  255.                         }
  256.                 }
  257.                 else                        //顯示日期
  258.                 {
  259.                         NOT = 0;
  260.                         for ( i = 0; i < 6; i++ )
  261.                         {
  262.                                 if ( i != WeiTwinkle &&  i != WeiTwinkle + 1 )         //不閃爍的位
  263.                                 {
  264.                                         P2 = WEI_CODE[ i ];
  265.                                         P0 = Display_Buffer[ i + 6 ];
  266.                                         DelayMS(2);
  267.                                 }
  268.                                 else if ( j > DelayTwinkle )   //閃爍的位(2位)
  269.                                 {
  270.                                         for ( k = 0; k < TimeTwinkle; k++ )
  271.                                         {
  272.                                                 P2 = WEI_CODE[ i ];
  273.                                                 P0 = Display_Buffer[ i + 6 ];
  274.                                                 DelayMS( 1 );
  275.                                                 P2 = WEI_CODE[ i+1 ];
  276.                                                 P0 = Display_Buffer[ i + 7 ];
  277.                                                 DelayMS( 1 );
  278.                                         }
  279.                                         j = 0;
  280.                                 }
  281.                                 P2 = 0xFF;
  282.                                 P0 = 0xFF;
  283.                                 DelayMS(1);
  284.                                 j++;
  285.                         }
  286.                 }
  287.         }
  288. }

  289. //掃描鍵盤
  290. void Scan_Key()
  291. {
  292.         //設(shè)置
  293.         if ( K_Setup == 0 )        
  294.         {
  295.                 DelayMS( TimeShake );                   //去抖動(dòng)
  296.                 if ( K_Setup == 0 )
  297.                 {
  298.                         Set_State ++;

  299.                         if ( Set_State > 6 )
  300.                         {
  301.                                 Set_State = 0;
  302.                                 DateTime_State = 0;
  303.                                 WeiTwinkle = 0;
  304.                         }
  305.                         else
  306.                         {
  307.                                 switch ( Set_State )
  308.                                 {
  309.                                         case 0:
  310.                                                 WeiTwinkle = 0;
  311.                                                 break;
  312.                                         case 1:
  313.                                                 WeiTwinkle = 0;
  314.                                                 break;
  315.                                         case 2:
  316.                                                 WeiTwinkle = 2;
  317.                                                 break;
  318.                                         case 3:
  319.                                                 WeiTwinkle = 4;
  320.                                                 break;
  321.                                         case 4:
  322.                                                 WeiTwinkle = 0;
  323.                                                 break;
  324.                                         case 5:
  325.                                                 WeiTwinkle = 2;
  326.                                                 break;
  327.                                         case 6:
  328.                                                 WeiTwinkle = 4;
  329.                                                 break;
  330.                                 }

  331.                                 if ( Set_State < 4 )
  332.                                 {
  333.                                         DateTime_State = 0;                //第一頁(yè),顯示時(shí)間
  334.                                 }
  335.                                 else
  336.                                 {
  337.                                         DateTime_State = 1;                //第二頁(yè),顯示日期
  338.                                 }
  339.                         }
  340.                         DelayMS(1);
  341.                         Play();
  342.                 }
  343.         }
  344.         
  345.         //在設(shè)置時(shí)才能操作的按鍵
  346.         if ( Set_State != 0 )
  347.         {
  348.                 //調(diào)時(shí):增加(設(shè)置狀態(tài)有效)
  349.                 if ( K_Add == 0 )        
  350.                 {
  351.                         DelayMS( TimeShake );                   //去抖動(dòng)
  352.                         if ( K_Add == 0 )
  353.                         {
  354.                                 switch( WeiTwinkle )
  355.                                 {
  356.                                         case 0:                //時(shí)/年
  357.                                                 if ( DateTime_State == 0 )
  358.                                                 {                        //小時(shí)
  359.                                                         Current_Time[2]++;
  360.                                                         if ( Current_Time[2] > 23 )
  361.                                                         {
  362.                                                                 Current_Time[2] = 0;
  363.                                                         }
  364.                                                         Display_Buffer[0] = DSY_CODE[ Current_Time[2] / 10 ];
  365.                                                         Display_Buffer[1] = DSY_CODE[ Current_Time[2] % 10 ];
  366.                                                 }
  367.                                                 else
  368.                                                 {                        //年
  369.                                                         Current_Time[6]++;
  370.                                                         Display_Buffer[6] = DSY_CODE[ Current_Time[6] / 10 ];
  371.                                                         Display_Buffer[7] = DSY_CODE[ Current_Time[6] % 10 ];
  372.                                                 }
  373.                                                 break;
  374.                                         case 2:                //分/月
  375.                                                 if ( DateTime_State == 0 )
  376.                                                 {                //分
  377.                                                         Current_Time[1]++;
  378.                                                         if ( Current_Time[1] > 59 )
  379.                                                         {
  380.                                                                 Current_Time[1] = 0;
  381.                                                         }
  382.                                                         Display_Buffer[2] = DSY_CODE[ Current_Time[1] / 10 ];
  383.                                                         Display_Buffer[3] = DSY_CODE[ Current_Time[1] % 10 ];
  384.                                                 }
  385.                                                 else
  386.                                                 {                //月
  387.                                                         Current_Time[4]++;
  388.                                                         if ( Current_Time[4] > 12 )
  389.                                                         {
  390.                                                                 Current_Time[4] = 1;
  391.                                                         }
  392.                                                         Display_Buffer[8] = DSY_CODE[ Current_Time[4] / 10 ];
  393.                                                         Display_Buffer[9] = DSY_CODE[ Current_Time[4] % 10 ];
  394.                                                 }
  395.                                                 break;
  396.                                         case 4:                //秒/日
  397.                                                 if ( DateTime_State == 0 )
  398.                                                 {                //秒
  399.                                                         Current_Time[0]++;
  400.                                                         if ( Current_Time[0] > 59 )
  401.                                                         {
  402.                                                                 Current_Time[0] = 0;
  403.                                                         }
  404.                                                         Display_Buffer[4] = DSY_CODE[ Current_Time[0] / 10 ];
  405.                                                         Display_Buffer[5] = DSY_CODE[ Current_Time[0] % 10 ];
  406.                                                 }
  407.                                                 else
  408.                                                 {                //日
  409.                                                         Current_Time[3]++;
  410.                                                         if ( Current_Time[3] > 31 )
  411.                                                         {
  412.                                                                 Current_Time[3] = 1;
  413.                                                         }
  414.                                                         Display_Buffer[10] = DSY_CODE[ Current_Time[3] / 10 ];
  415.                                                         Display_Buffer[11] = DSY_CODE[ Current_Time[3] % 10 ];
  416.                                                 }
  417.                                                 break;
  418.                                 }
  419.                                 Play();
  420.                         }
  421.                 }

  422.                 //調(diào)時(shí):減。ㄔO(shè)置狀態(tài)有效)
  423.                 if ( K_Sub == 0 )        
  424.                 {
  425.                         DelayMS( TimeShake );                   //去抖動(dòng)
  426.                         if ( K_Sub == 0 )
  427.                         {
  428.                                 switch( WeiTwinkle )
  429.                                 {
  430.                                         case 0:                //時(shí)/年
  431.                                                 if ( DateTime_State == 0 )
  432.                                                 {                        //小時(shí)
  433.                                                         Current_Time[2]--;
  434.                                                         if ( Current_Time[2] < 0 )
  435.                                                         {
  436.                                                                 Current_Time[2] = 23;
  437.                                                         }
  438.                                                         Display_Buffer[0] = DSY_CODE[ Current_Time[2] / 10 ];
  439.                                                         Display_Buffer[1] = DSY_CODE[ Current_Time[2] % 10 ];
  440.                                                 }
  441.                                                 else
  442.                                                 {                        //年
  443.                                                         Current_Time[6]--;
  444.                                                         if ( Current_Time[6] < 0 )
  445.                                                         {
  446.                                                                 Current_Time[6] = 0;
  447.                                                         }
  448.                                                         Display_Buffer[6] = DSY_CODE[ Current_Time[6] / 10 ];
  449.                                                         Display_Buffer[7] = DSY_CODE[ Current_Time[6] % 10 ];
  450.                                                 }
  451.                                                 break;
  452.                                         case 2:                //分/月
  453.                                                 if ( DateTime_State == 0 )
  454.                                                 {                //分
  455.                                                         Current_Time[1]--;
  456.                                                         if ( Current_Time[1] < 0 )
  457.                                                         {
  458.                                                                 Current_Time[1] = 59;
  459.                                                         }
  460.                                                         Display_Buffer[2] = DSY_CODE[ Current_Time[1] / 10 ];
  461.                                                         Display_Buffer[3] = DSY_CODE[ Current_Time[1] % 10 ];
  462.                                                 }
  463.                                                 else
  464.                                                 {                //月
  465.                                                         Current_Time[4]--;
  466.                                                         if ( Current_Time[4] <= 0 )
  467.                                                         {
  468.                                                                 Current_Time[4] = 12;
  469.                                                         }
  470.                                                         Display_Buffer[8] = DSY_CODE[ Current_Time[4] / 10 ];
  471.                                                         Display_Buffer[9] = DSY_CODE[ Current_Time[4] % 10 ];
  472.                                                 }
  473.                                                 break;
  474.                                         case 4:                //秒/日
  475.                                                 if ( DateTime_State == 0 )
  476.                                                 {                //秒
  477.                                                         Current_Time[0]--;
  478.                                                         if ( Current_Time[0] < 0 )
  479.                                                         {
  480.                                                                 Current_Time[0] = 59;
  481.                                                         }
  482.                                                         Display_Buffer[4] = DSY_CODE[ Current_Time[0] / 10 ];
  483.                                                         Display_Buffer[5] = DSY_CODE[ Current_Time[0] % 10 ];
  484.                                                 }
  485.                                                 else
  486.                                                 {                //日
  487.                                                         Current_Time[3]--;
  488.                                                         if ( Current_Time[3] <= 0 )
  489.                                                         {
  490.                                                                 Current_Time[3] = 31;
  491.                                                         }
  492.                                                         Display_Buffer[10] = DSY_CODE[ Current_Time[3] / 10 ];
  493.                                                         Display_Buffer[11] = DSY_CODE[ Current_Time[3] % 10 ];
  494.                                                 }
  495.                                                 break;
  496.                                 }
  497.                                 Play();
  498.                         }
  499.                 }
  500.         
  501.                 //保存數(shù)據(jù)并退回到走時(shí)狀態(tài)(設(shè)置狀態(tài)有效)
  502.                 if ( K_OK == 0 )         
  503.                 {
  504.                         DelayMS( TimeShake );                   //去抖動(dòng)
  505.                         if ( K_OK == 0 )
  506.                         {
  507.                                 SET_DS1302();
  508.                                 Set_State = 0;
  509.                                 Play();
  510.                         }
  511.                 }

  512.                 //日期格式化,使日期時(shí)間值為合法數(shù)據(jù)(這個(gè)按鍵不安裝在機(jī)殼上,如要操作,直接用杜邦線短接既可。)
  513.                 if ( K_FORMAT == 0 )
  514.                 {
  515.                         DelayMS( TimeShake );
  516.                         if ( K_FORMAT == 0 )
  517.                         {
  518.                                 Format_DS1302();
  519.                                 Set_State = 0;
  520.                         }
  521.                 }
  522.         }
  523.         else
  524.         {
  525.                 //走時(shí)狀態(tài)(切換日期與時(shí)間)
  526.                 if ( K_OK == 0 )         
  527.                 {
  528.                         DelayMS( TimeShake );                   //去抖動(dòng)
  529.                         if ( K_OK == 0 )
  530.                         {
  531.                                 DateTime_State = ~DateTime_State;
  532.                                 DelayMS(1);
  533.                                 Play();
  534.                         }
  535.                 }
  536.         }
  537. }

  538. //判斷是否是閏年
  539. //uchar isLeapYear(uint y)
  540. //{
  541. //        return ( y % 4 == 0 && y % 100 != 0 ) || ( y % 400 == 0 );
  542. //}

  543. //系統(tǒng)初始化
  544. //T0 用于鍵盤掃描,每50ms一次。
  545. void Init()
  546. {
  547.         K_GND = 0;                //薄膜開關(guān)的地。
  548.         TMOD = 0x01;        //設(shè)置定時(shí)器0、1為工作方式1
  549.         TH0 = 0;                //65.536ms
  550.         TL0 = 0;
  551.         ET0 = 1;        //允許定時(shí)器0
  552.         TR0 = 1;        //啟動(dòng)定時(shí)器0
  553.         EA = 1;                //全局中斷開
  554. }

  555. //主函數(shù)
  556. void main()
  557. {
  558.         Init();
  559.         while(1)
  560.         {
  561.                 if ( Set_State == 0 )        //走時(shí)狀態(tài)
  562.                 {
  563.                         GetTime();                        //讀取時(shí)間數(shù)據(jù)(運(yùn)行時(shí)間約 2.4ms)
  564.                 }
  565.                 LedDisplay();
  566.         }
  567. }

  568. //定時(shí)器0中斷
  569. void Time0() interrupt 1
  570. {
  571.         TR0 = 0;        //關(guān)閉定時(shí)器0
  572.         Scan_Key();                  //掃描鍵盤
  573.         TH0 = 0;                //65.536ms產(chǎn)生一次中斷
  574.         TL0 = 0;
  575.         TR0 = 1;        //啟動(dòng)定時(shí)器0
  576. }

  577. //定時(shí)器1中斷
  578. //控制蜂鳴器2秒響一聲
  579. //void Time1() interrupt 3
  580. //{
  581. //        TR1 = 0;
  582. //        if ( BeepTime >= 40 )
  583. //        {
  584. ////                Play();
  585. //                BeepTime = 0;
  586. //        }
  587. //        BeepTime++;
  588. //        TH1 = ( 65536 - 50000 ) / 256;
  589. //        TL1 = ( 65536 - 50000 ) % 256;
  590. //        TR1 = 1;
  591. //}
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

ID:141556 發(fā)表于 2020-3-31 08:29 | 顯示全部樓層
手工真好。
回復(fù)

使用道具 舉報(bào)

ID:691573 發(fā)表于 2020-3-31 09:08 | 顯示全部樓層
不錯(cuò)不錯(cuò),贊一個(gè)。。!好資料,51黑有你更精彩!!!
回復(fù)

使用道具 舉報(bào)

ID:284488 發(fā)表于 2020-3-31 09:09 | 顯示全部樓層
好東東啊!謝謝樓主的分享。
回復(fù)

使用道具 舉報(bào)

ID:388929 發(fā)表于 2020-3-31 10:28 | 顯示全部樓層
動(dòng)手能力強(qiáng),不錯(cuò),而已很漂亮
回復(fù)

使用道具 舉報(bào)

ID:342822 發(fā)表于 2020-3-31 13:00 | 顯示全部樓層
數(shù)碼管前貼黑膜~~~
回復(fù)

使用道具 舉報(bào)

ID:143767 發(fā)表于 2020-3-31 17:30 | 顯示全部樓層
有定鬧功能嗎?
回復(fù)

使用道具 舉報(bào)

ID:97023 發(fā)表于 2020-3-31 21:56 | 顯示全部樓層

暫時(shí)沒(méi)有,包括日期、時(shí)間設(shè)置都還沒(méi)有進(jìn)行限制。
回復(fù)

使用道具 舉報(bào)

ID:97023 發(fā)表于 2020-3-31 21:57 | 顯示全部樓層
taotie 發(fā)表于 2020-3-31 13:00
數(shù)碼管前貼黑膜~~~

謝謝,還沒(méi)想到這一點(diǎn)。
回復(fù)

使用道具 舉報(bào)

ID:584814 發(fā)表于 2020-4-2 10:36 | 顯示全部樓層
手工能力超贊
回復(fù)

使用道具 舉報(bào)

ID:116662 發(fā)表于 2020-4-4 20:17 | 顯示全部樓層
這需要時(shí)間呀,多謝樓主分享
回復(fù)

使用道具 舉報(bào)

ID:282850 發(fā)表于 2020-4-8 17:14 | 顯示全部樓層
裝1個(gè)DS18B20測(cè)溫,如果用2個(gè),一個(gè)測(cè)室外溫度,一個(gè)測(cè)室內(nèi)。我經(jīng)常出門才知道衣服不夠。
DS18b20精度、可靠性極高。程序想必你有了,如需要,我發(fā)給你。當(dāng)然如果用無(wú)線把室外溫度傳來(lái)更好,推薦nrf24L01,不過(guò)MCU要低功耗的。
回復(fù)

使用道具 舉報(bào)

ID:34298 發(fā)表于 2020-4-8 20:32 | 顯示全部樓層
費(fèi)勁做的最后時(shí)間誤差太大 還是扔了 換成ds3231吧
回復(fù)

使用道具 舉報(bào)

ID:690448 發(fā)表于 2020-4-8 21:54 | 顯示全部樓層
樓主手藝好,殼子漂亮,但是瓤子太單調(diào),建議換我這個(gè)方案。

20200323_135350.jpg



20200323_150835.jpg




101.jpg

評(píng)分

參與人數(shù) 1黑幣 +10 收起 理由
王朗的誘惑 + 10 優(yōu)雅

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:630491 發(fā)表于 2020-4-13 18:58 | 顯示全部樓層
推薦樓主學(xué)習(xí)ad,這樣的話設(shè)計(jì)出pcb直接交付制作,這樣只需要焊接元件,不需要焊接線路了
回復(fù)

使用道具 舉報(bào)

ID:704585 發(fā)表于 2020-4-16 10:05 | 顯示全部樓層
多謝樓主分享。
回復(fù)

使用道具 舉報(bào)

ID:66679 發(fā)表于 2020-4-18 21:55 | 顯示全部樓層

不錯(cuò)不錯(cuò),贊一個(gè)。。!好資料,51黑有你更精彩!!!
回復(fù)

使用道具 舉報(bào)

ID:97023 發(fā)表于 2020-4-27 00:42 | 顯示全部樓層
1679079206 發(fā)表于 2020-4-13 18:58
推薦樓主學(xué)習(xí)ad,這樣的話設(shè)計(jì)出pcb直接交付制作,這樣只需要焊接元件,不需要焊接線路了

謝謝推薦,其實(shí)AD我會(huì)的,只是平時(shí)制作一些小東西,專門去打板有點(diǎn)不劃算。
年青時(shí)候不喜歡洞洞板,覺得一邊焊接,一邊思考,太痛苦了,特別是焊接好了以后要拆下來(lái),更難。
最近幾年接觸到了洞洞板布線軟件:LochMaster 4.0,先規(guī)劃再焊接,這樣輕松多了,目前對(duì)我來(lái)說(shuō)用洞洞板制作是一種享受。至于打板,等今后制作更復(fù)雜的東西再說(shuō)吧。
對(duì)你的《USB轉(zhuǎn)TTL模塊制作》文章很感興趣,期待著更新。
回復(fù)

使用道具 舉報(bào)

ID:128463 發(fā)表于 2020-5-25 16:45 | 顯示全部樓層
多謝樓主分享!!!
回復(fù)

使用道具 舉報(bào)

ID:430492 發(fā)表于 2020-5-25 19:15 | 顯示全部樓層
做得不錯(cuò),動(dòng)手能力很棒!
回復(fù)

使用道具 舉報(bào)

ID:743028 發(fā)表于 2020-5-26 10:35 來(lái)自手機(jī) | 顯示全部樓層
收藏一下
回復(fù)

使用道具 舉報(bào)

ID:56960 發(fā)表于 2020-8-3 14:22 | 顯示全部樓層
樓主強(qiáng)大,木制機(jī)箱是亮點(diǎn),榫鉚結(jié)構(gòu)!
回復(fù)

使用道具 舉報(bào)

ID:23303 發(fā)表于 2021-9-21 15:50 | 顯示全部樓層
下載學(xué)習(xí)一下,謝謝樓主分享!
回復(fù)

使用道具 舉報(bào)

ID:908826 發(fā)表于 2021-9-21 16:58 | 顯示全部樓層
博主可以試試ds3231,這玩意還有溫度采集功能。我覺得挺好用的
回復(fù)

使用道具 舉報(bào)

ID:1011444 發(fā)表于 2022-6-30 20:43 | 顯示全部樓層
樓主的動(dòng)手能力,一個(gè)字“棒”,三個(gè)字“非常棒”,做出的產(chǎn)品幾乎達(dá)到適用的機(jī)制水平,這對(duì)手工制作電子產(chǎn)品的電子業(yè)余愛好者來(lái)說(shuō),要做到是非常不容易。我也是diy愛好者,業(yè)余時(shí)間學(xué)點(diǎn)兒?jiǎn)纹瑱C(jī)知識(shí),樓主應(yīng)為我的學(xué)習(xí)的榜樣。多謝了
回復(fù)

使用道具 舉報(bào)

ID:832201 發(fā)表于 2022-7-3 23:35 | 顯示全部樓層
佩服,
回復(fù)

使用道具 舉報(bào)

ID:870445 發(fā)表于 2022-7-31 12:46 | 顯示全部樓層
看到這個(gè) 真不錯(cuò),正想做一個(gè),謝謝了
回復(fù)

使用道具 舉報(bào)

ID:1064667 發(fā)表于 2023-7-25 17:19 | 顯示全部樓層
真不錯(cuò),花了不少時(shí)間吧
回復(fù)

使用道具 舉報(bào)

ID:397054 發(fā)表于 2023-7-29 17:49 | 顯示全部樓層
同好啊,前兩年我也做了個(gè),形式跟你這個(gè)差不多,呵呵:

開工

開工


焊接中

焊接中



基本焊好

基本焊好



去年電路板上斷了根線,缺比劃,一直沒(méi)功夫弄它,放在書架上吃了不少灰,前幾天把它翻出來(lái)打算弄好那根線并修改一下程序:

51hei圖片_20230729173223.jpg

回復(fù)

使用道具 舉報(bào)

ID:1089276 發(fā)表于 2023-7-30 06:48 | 顯示全部樓層
相當(dāng)?shù)呐2?/td>
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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