久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 9206|回復: 0
打印 上一主題 下一主題
收起左側

簡明DS1302溫度LED時鐘制作詳解(附單片機源碼與PCB)

[復制鏈接]
跳轉到指定樓層
樓主
回顧
這是樓主在高三時候做的一個項目,我和我的組員們共同完成了這個小鐘從電路設計,焊接,再到編程調試的過程。我們將之前學習到的單片機和電路知識運用起來,雖然經歷了不計其數的Bug和坎坷,可是就是在這樣痛苦的過程中我們不知不覺中成長了許多,收獲了更多的實戰經驗。
提出
一直以來,我多數在開發軟件,偶爾碰碰Arduino實現點小功能,幸運的是我的高中有機器人實驗室,于是我們就在龔鵬老師的帶領下,系統的學習STC單片機開發和基礎硬件知識。上個學期,課程已經基本學完,在7*5點陣的基礎下,我們幾個都想獨立自主的完成一個有規模的項目,在大家的提議下,我們選擇去做一個可以顯示溫度的LED時鐘,而且顯示要用LED才大氣,于是我們開始了有序的準備工作。
實現
為了實現這個小鐘的預期功能,我們聽取了老師的意見。使用STC15W402AS芯片(宏晶科技生產)作為主控芯片,利用LED小燈組成的4個“8”作為顯示部分,同時使用DS1302(Maxim生產)作為系統時鐘芯片,使用DS18B20(Maxim生產)作為溫度傳感器芯片。電源使用MicroUSB+5V供電。電路圖為自行設計,使用Protel繪制,再有工廠加工,隨后按電路圖焊接原件,最后進行編程調試。
圖片展示

結構
使用STC15W402AS芯片(宏晶科技生產)作為主控芯片,利用LED小燈組成的4個“8”作為顯示部分,同時使用DS1302(Maxim生產)作為系統時鐘芯片,使用DS18B20(Maxim生產)作為溫度傳感器芯片。電源使用MicroUSB+5V供電。電路圖為自行設計。
重要邏輯顯示原理 - 視覺暫留掃描
由于我們使用了類似于放大版“數碼管”的顯示方式,限于單片機引腳數量限制,我們不能把每個8的每個部分都和單片機相連。于是我們采用了現在LED顯示屏的顯示原理--掃描點亮的原理。在我們的電路中,我們將4個“8”的8個組成部分(a,b,c,d,e,f,g)的正極和單片機P1端口(恰好8個端口)連接(也就是把每個“8”的a并連起來接到一個單片機引腳,把每個“8”的b并連起來接到另一個單片機引腳,以此類推),再將每個“8”的所有組成部分的所有負極并聯,分別和單片機上P2端口上的4個引腳相連,組成顯示控制電路。需要點亮第1個“8”時就先將這個“8”的負極引腳置低,再將需要點亮的部分引腳同時置高。例如下圖所示想要顯示“1”,就將b,c的引腳置高


這樣問題就來了:現在我們能一個一個點亮了,如果我讓這4個“8”一起亮怎么辦?
這就需要視覺暫留原理了,大家都知道電影之所以能動起來就是因為我們人眼有0.1秒的視覺暫留。我們點亮小燈也如此,先點亮第一個,延遲5ms,再點亮第二個,延遲5ms,以此類推。5ms這樣短的時間人根本看不出閃動感,于是完整的圖像顯示出來。
下面是時間送顯的代碼(chart數組里是預先設計好的自模):
  1. void convertShow(char hour_s1,hour_s2,min_s1,min_s2)
  2. {

  3.     E1 = 0;
  4.     P1 = chart[hour_s1];
  5.     delayMS(5);
  6.     P1 = allclear;
  7.     E1 = 1;

  8.     E2 = 0;
  9.     P1 = chart[hour_s2];
  10.     delayMS(5);
  11.     P1 = allclear;
  12.     E2 = 1;

  13.     E3 = 0;
  14.     P1 = chart[min_s1];
  15.     delayMS(5);
  16.     P1 = allclear;
  17.     E3 = 1;

  18.     E4 = 0;
  19.     P1 = chart[min_s2];
  20.     delayMS(5);
  21.     P1 = allclear;
  22.     E4 = 1;
  23.     if(sec_2%0x02==0x01)
  24.     {
  25.         MDLIGHT = 0;
  26.     }
  27.     else
  28.     MDLIGHT = 1;
復制代碼

讀取時間和溫度
這個想起來很簡單,無非是單片機一邊顯示,一邊不斷向時鐘芯片或者溫度芯片詢問數據,至于芯片如何驅動,則是后面要講的重頭戲
時間修改/模式切換 - 按鈕的使用
誰家的鐘不能改時間啊,所以我們要支持時間修改功能,于是我們決定用傳統的按鈕來修改時間。使用三個按鈕(稱呼他們為Btn1,Btn2,Btn3)。Btn1負責加時間,短按是加1,長按遞加,直到松開。Btn2和Btn1相反,而Btn3則是模式切換(一共三種:修改小時,修改分鐘,顯示溫度)。
可是在實際編程時我們發現,按鈕只要收到輕微擾動就響應,并不是按下才響應,這是為何?
原來通常的按鍵所用開關為機械彈性開關,當機械觸點斷開、閉合時,由于機械觸點的彈性作用,一個按鍵開關在閉合時不會馬上穩定地接通,在斷開時也不會一下子斷開。因而在閉合及斷開的瞬間均伴隨有一連串的抖動,為了不產生這種現象而作的措施就是按鍵消抖,如下圖。

看來我們需要軟件軟件消抖(硬件消抖效果好可是我們的電路圖已經印刷了啊)。軟件消抖即檢測出鍵閉合后執行一個延時程序,5ms~10ms的延時,讓前沿抖動消失后再一次檢測鍵的狀態,如果仍保持閉合狀態電平,則確認為真正有鍵按下。當檢測到按鍵釋放后,也要給5ms~10ms的延時,待后沿抖動消失后才能轉入該鍵的處理程序。程序如下:
  1. if (KEY_1==0 || KEY_2==0 || KEY_3==0)
  2.     {
  3.         delayMS(20);        //20毫秒軟件防抖
  4.         if (KEY_1 == 0)
  5.         {
  6.             keyValue = 1;
  7.             while(KEY_1==0)
  8.             {
  9.                 modifyTime(status+8);
  10.                 delayShow(500);
  11.             }
  12.         }
  13.         if (KEY_2 == 0)
  14.         {
  15.             keyValue = 2;
  16.             while(KEY_2==0)
  17.             {
  18.                 modifyTime(status+16);
  19.                 delayShow(500);
  20.             }
  21.         }
  22.         if (KEY_3 == 0)
  23.         {
  24.             keyValue = 3;
  25.         }
  26.     }
  27. }
復制代碼

下面是按鈕修改的代碼:
  1. /*************按鈕掃描函數******************************/
  2. void keyScan()
  3. {
  4.     if (KEY_1==0 || KEY_2==0 || KEY_3==0)
  5.     {
  6.         delayMS(20);        //20毫秒軟件防抖
  7.         if (KEY_1 == 0)
  8.         {
  9.             keyValue = 1;
  10.             while(KEY_1==0)
  11.             {
  12.                 modifyTime(status+8);
  13.                 delayShow(500);
  14.             }
  15.         }
  16.         if (KEY_2 == 0)
  17.         {
  18.             keyValue = 2;
  19.             while(KEY_2==0)
  20.             {
  21.                 modifyTime(status+16);
  22.                 delayShow(500);
  23.             }
  24.         }
  25.         if (KEY_3 == 0)
  26.         {
  27.             keyValue = 3;
  28.         }
  29.     }
  30. }

  31. /*************按鈕響應處理函數******************************/
  32. void keyHandle()
  33. {
  34.     if(keyValue==1)
  35.     {
  36.         DS1302_Write(sec,min,hour,day,month,week,year);
  37.         keyValue = 0;
  38.     }
  39.     else if(keyValue==2)
  40.     {
  41.         DS1302_Write(sec,min,hour,day,month,week,year);
  42.         keyValue = 0;
  43.     }
  44.     else if(keyValue==3)
  45.     {
  46.         if (status==1)
  47.         {
  48.             status = 2;
  49.         }
  50.         else if(status==2)
  51.         {
  52.             status = 3;
  53.         }
  54.         else if(status==3)
  55.         {
  56.             status = 1;
  57.         }
  58.         keyValue = 0;

  59.     }
  60. }
復制代碼

還有修改時間的一些詭異邏輯代碼,涉及到一些標志變量,請仔細研讀體會:
  1. /*************修改時間函數******************************/
  2. void modifyTime(int mode)  //mode指明修改小時或分鐘   1:小時   2:分鐘
  3. {

  4.     //修改小時(1)+遞增(8)
  5.     if(mode == 9)
  6.     {
  7.         if(hour==0x23)
  8.         {
  9.             hour = 0x00;
  10.         }
  11.         else if(hour==0x09)
  12.         {
  13.             hour=0x10;
  14.         }
  15.         else if(hour==0x19)
  16.         {
  17.             hour=0x20;
  18.         }
  19.         else
  20.         {
  21.             hour=hour+0x01;
  22.         }

  23.         timeConvert();
  24.         convertShow(hour_1,hour_2,min_1,min_2);
  25.     }

  26.     //修改小時(1)+遞減(16)
  27.     if(mode == 17)
  28.     {
  29.         if(hour==0x00)
  30.         {
  31.             hour = 0x23;
  32.         }
  33.         else if(hour==0x10)
  34.         {
  35.             hour = 0x09;
  36.         }
  37.         else if(hour==0x20)
  38.         {
  39.             hour = 0x19;
  40.         }
  41.         else
  42.         {
  43.             hour = hour-0x01;
  44.         }

  45.         timeConvert();
  46.         convertShow(hour_1,hour_2,min_1,min_2);
  47.     }

  48.     //修改分鐘(2)+遞增(8)
  49.     if(mode == 10)
  50.     {

  51.         if(min==0x59)
  52.         {
  53.             min=0x00;
  54.         }
  55.         else if(min-(min_1<<4)==0x09)
  56.         {
  57.             min=(min_1+0x01)<<4;
  58.         }
  59.         else
  60.         {
  61.             min=min+0x01;
  62.         }

  63.         timeConvert();
  64.         convertShow(hour_1,hour_2,min_1,min_2);
  65.     }

  66.     //修改分鐘(2)+遞減(16)
  67.     if(mode == 18)
  68.     {
  69.         if(min==0x00)
  70.         {
  71.             min=0x59;
  72.         }
  73.         else if(min_2==0x00)
  74.         {
  75.             min=min-0x10;
  76.             min=min+0x09;
  77.         }
  78.         else
  79.         {
  80.             min=min-0x01;
  81.         }

  82.         timeConvert();
  83.         convertShow(hour_1,hour_2,min_1,min_2);
  84.     }
  85. }
復制代碼

整體邏輯
各部分的邏輯設計都完成了,我們現在開始設計整個程序的主函數部分。單片機上電后首先初始化(包括引腳置低什么的不再贅述)檢測DS1302是否在運行(內置電池可以掉電走時),如果在運行就讀取時間送顯,不在運行就起振(開始走時)。然后在每個顯示函數過后偵測按鈕操作,如果發現有效按鈕操作就進行處理按鈕的邏輯,該修改時間就修改時間,該顯示溫度就顯示溫度。這個流程用死循環加以嵌套,就可以無止無休的運行下去(不斷電的話)。下面是主函數代碼:
  1. void main()
  2. {
  3.     init();

  4.     while(1)
  5.     {
  6.         if(status==3)
  7.         {
  8.             temp = DS18B20_ReadTemp();
  9.             tempHandle();
  10.             tempshow(temp_1,temp_2);
  11.         }
  12.         else
  13.         {
  14.             DS1302_readtime();
  15.             convertShow(hour_1,hour_2,min_1,min_2);
  16.         }
  17.         keyScan();
  18.         if(keyValue!=0&&KEY_1==1&&KEY_2==1&&KEY_3==1)
  19.         {
  20.             keyHandle();
  21.         }
  22.     }
  23. }
復制代碼

下面是初始化函數:
  1. void init()
  2. {
  3.     //關閉所有小燈
  4.     E1=1;
  5.     E2=1;
  6.     E3=1;
  7.     E4=1;
  8.     MDLIGHT = 1;
  9.     P1 = allclear;
  10.     T_CE = 0;
  11.     T_SCLK = 0;

  12.     //默認初始化時間12:00
  13.     sec = 0x00;
  14.     min = 0x00;
  15.     hour = 0x16;
  16.     year = 0x01;
  17.     month = 0x01;
  18.     week = 0x01;
  19.     day = 0x01;
  20.     status = 1;
  21.     keyValue = 0;
  22.     delayMS(1000);
  23.     //DS1302初始化判斷是否存在后備電源

  24.     if(DS1302_Read(0x81)&0x80==0x80)
  25.     {
  26.         DS1302_Write_one(0x8e,0x00);
  27.         DS1302_Write_one(0x80,sec);  //起振
  28.         DS1302_Write_one(0x8e,0x80);
  29.     }
  30.     else
  31.     {

  32.     }
  33. }
復制代碼

下面附上DS1302類庫,親測好用:
  1. /*************寫入一字節****************/
  2. void DS1302_Input_Byte(char Input)  //向時鐘IC寫入一字節
  3. {
  4.     char i;
  5.     T_SCLK = 0;
  6.     delay2us();
  7.     ACC =Input;
  8.     for(i=8; i>0; i--)
  9.     {
  10.         T_DIO = ACC_0;            //相當于匯編中的 RRC
  11.         delay2us();
  12.         T_SCLK = 1;
  13.         delay2us();
  14.         T_SCLK = 0;
  15.         ACC = ACC >> 1;
  16.     }
  17. }

  18. /*************讀取一字節****************/
  19. char DS1302_Output_Byte(void)      //從時鐘IC讀取一字節()
  20. {
  21.     char i;
  22.     for(i=8; i>0; i--)
  23.     {
  24.         ACC>>=1;
  25.         T_DIO= 1;
  26.         delay2us();
  27.         ACC_7 = T_DIO;
  28.         T_SCLK = 1;                 //相當于匯編中的 RRC
  29.         delay2us();
  30.         T_SCLK = 0;
  31.         delay2us();
  32.     }
  33.     T_DIO = 0;
  34.     delay2us();
  35.     return(ACC);
  36. }

  37. /*************寫一字節數據****************/
  38. void DS1302_Write_one( char addr,dat )       // 寫入地址、數據子程序
  39. {
  40.     T_CE=0;                             //T_CE引腳為低,數據傳送中止
  41.     T_SCLK=0;                          //清零時鐘總線
  42.     T_CE = 1;                          //T_CE引腳為高,邏輯控制有效
  43.     DS1302_Input_Byte(addr);           // 地址,命令
  44.     DS1302_Input_Byte(dat);          // 寫1Byte數據
  45.     T_SCLK = 1;
  46.     T_CE = 0;
  47. }

  48. /*************讀一字節數據****************/
  49. char DS1302_Read ( char addr )    //數據讀取子程序
  50. {
  51.     char date;
  52.     T_CE=0;
  53.     T_SCLK=0;
  54.     T_CE = 1;
  55.     DS1302_Input_Byte(addr);        // 地址,命令
  56.     date = DS1302_Output_Byte();         // 讀1Byte數據
  57.     T_SCLK = 1;
  58.     T_CE = 0;
  59.     return(date);
  60. }


  61. /*************寫入時間數據****************/
  62. void DS1302_Write(char sec_w,min_w,hour_w,day_w,month_w,week_w,year_w)
  63. {
  64.     DS1302_Write_one(0x8e,0x00);
  65.     DS1302_Write_one(0x82,min_w);
  66.     DS1302_Write_one(0x84,hour_w);
  67.     DS1302_Write_one(0x86,day_w);
  68.     DS1302_Write_one(0x88,month_w);
  69.     DS1302_Write_one(0x8a,week_w);
  70.     DS1302_Write_one(0x8c,year_w);
  71.     DS1302_Write_one(0x80,sec_w);
  72.     DS1302_Write_one(0x8e,0x80);

  73. }

  74. /*************時間轉換為顯示格式****************/
  75. void timeConvert()
  76. {
  77.     sec_1 = sec>>4;
  78.     sec_2 = sec&0x0f;
  79.     min_1 = min>>4;
  80.     min_2 = min&0x0f;
  81.     hour_1 = hour>>4;
  82.     hour_2 = hour&0x0f;

  83. }

  84. /*************從芯片讀取時間****************/
  85. void DS1302_readtime()
  86. {
  87.     sec=DS1302_Read(0x81);                    //讀秒
  88.     min=DS1302_Read(0x83);                    //讀分
  89.     hour=DS1302_Read(0x85);                   //讀時
  90.     day=DS1302_Read(0x87);                    //讀日
  91.     month=DS1302_Read(0x89);                  //讀月
  92.     year=DS1302_Read(0x8d);                   //讀年
  93.     week=DS1302_Read(0x8b);                   //讀星期
  94.     timeConvert();

  95. }
復制代碼

DIY教程Windows
1.克隆或下載本倉庫,PCB電路圖在倉庫內,印刷后按照引腳焊接元件。
2.下載宏晶科技官網所提供的相關燒錄軟件與教程,并安裝。
3.下載KeilC51開發工具,并安裝。
4.下載TKStudio,并安裝(可選)。
5.使用USB轉TTl燒錄器連接板載串口與計算機(如果需要驅動請自行安裝)
6.使用STC燒錄軟件,選擇STC15W402AS型號,使用默認配置(單片機震蕩頻率11.0592MHz),載入想要燒錄的二進制文件,上電燒錄。
7.如果需要增加修改邏輯代碼,可以使用TKStudio打開main-code/Clock.xmp進行二次開發,其他IDE也可。
最后附上代碼以及PCB:



全部資料51hei下載地址:
ds1302-stc15-clock-master.zip (184.78 KB, 下載次數: 73)

評分

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

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂 踩
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产欧美一区二区三区国产幕精品 | 欧美日韩国产一区二区三区不卡 | 成人在线不卡 | 日本三级精品 | 超碰伊人久久 | 国产一区二区三区精品久久久 | 国产欧美精品一区二区 | 亚洲欧美日韩激情 | 99久久久国产精品免费消防器 | 一区免费 | 国产精品久久久久久久久久软件 | 欧美日韩亚洲视频 | 欧美三级成人理伦 | 91福利在线观看视频 | 国产精品久久国产精品 | 精品一区二区三区免费毛片 | 免费激情网站 | 精品国产一区二区三区免费 | 天天操夜夜看 | 精品国产91久久久久久 | 亚洲网站在线观看 | 久久久久久国产精品久久 | 91精品国产综合久久精品 | 欧美黄在线观看 | 国产精品视频500部 a久久 | av播播| 久久国产精品免费 | 成人依人 | 日韩中文一区二区三区 | 成年人黄色小视频 | 操久久久 | 麻豆精品一区二区三区在线观看 | 毛片免费看 | 日韩毛片网| 亚洲夜夜爽 | 97精品一区二区 | 亚洲欧美激情视频 | 国产一区日韩在线 | 精品国产一区二区三区性色av | 国产精品99久久久久久www | 日韩一区二区三区在线视频 |