回顧 這是樓主在高三時候做的一個項目,我和我的組員們共同完成了這個小鐘從電路設計,焊接,再到編程調試的過程。我們將之前學習到的單片機和電路知識運用起來,雖然經歷了不計其數的Bug和坎坷,可是就是在這樣痛苦的過程中我們不知不覺中成長了許多,收獲了更多的實戰經驗。 提出一直以來,我多數在開發軟件,偶爾碰碰Arduino實現點小功能,幸運的是我的高中有機器人實驗室,于是我們就在龔鵬老師的帶領下,系統的學習STC單片機開發和基礎硬件知識。上個學期,課程已經基本學完,在7*5點陣的基礎下,我們幾個都想獨立自主的完成一個有規模的項目,在大家的提議下,我們選擇去做一個可以顯示溫度的LED時鐘,而且顯示要用LED才大氣,于是我們開始了有序的準備工作。 實現為了實現這個小鐘的預期功能,我們聽取了老師的意見。使用STC15W402AS芯片(宏晶科技生產)作為主控芯片,利用LED小燈組成的4個“8”作為顯示部分,同時使用DS1302(Maxim生產)作為系統時鐘芯片,使用DS18B20(Maxim生產)作為溫度傳感器芯片。電源使用MicroUSB+5V供電。電路圖為自行設計,使用Protel繪制,再有工廠加工,隨后按電路圖焊接原件,最后進行編程調試。 圖片展示
DSC_0093-300x199.jpg (9.89 KB, 下載次數: 73)
下載附件
2018-5-7 17:49 上傳
DSC_0072-min-300x199.jpg (14.98 KB, 下載次數: 69)
下載附件
2018-5-7 17:49 上傳
DSC_0088-min-300x199.jpg (12.15 KB, 下載次數: 73)
下載附件
2018-5-7 17:49 上傳
結構使用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的引腳置高
timg-215x300.jpg (12.57 KB, 下載次數: 80)
下載附件
2018-5-7 17:49 上傳
這樣問題就來了:現在我們能一個一個點亮了,如果我讓這4個“8”一起亮怎么辦? 這就需要視覺暫留原理了,大家都知道電影之所以能動起來就是因為我們人眼有0.1秒的視覺暫留。我們點亮小燈也如此,先點亮第一個,延遲5ms,再點亮第二個,延遲5ms,以此類推。5ms這樣短的時間人根本看不出閃動感,于是完整的圖像顯示出來。 下面是時間送顯的代碼(chart數組里是預先設計好的自模): - void convertShow(char hour_s1,hour_s2,min_s1,min_s2)
- {
- E1 = 0;
- P1 = chart[hour_s1];
- delayMS(5);
- P1 = allclear;
- E1 = 1;
- E2 = 0;
- P1 = chart[hour_s2];
- delayMS(5);
- P1 = allclear;
- E2 = 1;
- E3 = 0;
- P1 = chart[min_s1];
- delayMS(5);
- P1 = allclear;
- E3 = 1;
- E4 = 0;
- P1 = chart[min_s2];
- delayMS(5);
- P1 = allclear;
- E4 = 1;
- if(sec_2%0x02==0x01)
- {
- MDLIGHT = 0;
- }
- else
- MDLIGHT = 1;
復制代碼
讀取時間和溫度這個想起來很簡單,無非是單片機一邊顯示,一邊不斷向時鐘芯片或者溫度芯片詢問數據,至于芯片如何驅動,則是后面要講的重頭戲 時間修改/模式切換 - 按鈕的使用誰家的鐘不能改時間啊,所以我們要支持時間修改功能,于是我們決定用傳統的按鈕來修改時間。使用三個按鈕(稱呼他們為Btn1,Btn2,Btn3)。Btn1負責加時間,短按是加1,長按遞加,直到松開。Btn2和Btn1相反,而Btn3則是模式切換(一共三種:修改小時,修改分鐘,顯示溫度)。 可是在實際編程時我們發現,按鈕只要收到輕微擾動就響應,并不是按下才響應,這是為何?
原來通常的按鍵所用開關為機械彈性開關,當機械觸點斷開、閉合時,由于機械觸點的彈性作用,一個按鍵開關在閉合時不會馬上穩定地接通,在斷開時也不會一下子斷開。因而在閉合及斷開的瞬間均伴隨有一連串的抖動,為了不產生這種現象而作的措施就是按鍵消抖,如下圖。
20150722113229813.jpg (8.17 KB, 下載次數: 70)
下載附件
2018-5-7 17:49 上傳
看來我們需要軟件軟件消抖(硬件消抖效果好可是我們的電路圖已經印刷了啊)。軟件消抖即檢測出鍵閉合后執行一個延時程序,5ms~10ms的延時,讓前沿抖動消失后再一次檢測鍵的狀態,如果仍保持閉合狀態電平,則確認為真正有鍵按下。當檢測到按鍵釋放后,也要給5ms~10ms的延時,待后沿抖動消失后才能轉入該鍵的處理程序。程序如下: - if (KEY_1==0 || KEY_2==0 || KEY_3==0)
- {
- delayMS(20); //20毫秒軟件防抖
- if (KEY_1 == 0)
- {
- keyValue = 1;
- while(KEY_1==0)
- {
- modifyTime(status+8);
- delayShow(500);
- }
- }
- if (KEY_2 == 0)
- {
- keyValue = 2;
- while(KEY_2==0)
- {
- modifyTime(status+16);
- delayShow(500);
- }
- }
- if (KEY_3 == 0)
- {
- keyValue = 3;
- }
- }
- }
復制代碼
下面是按鈕修改的代碼:- /*************按鈕掃描函數******************************/
- void keyScan()
- {
- if (KEY_1==0 || KEY_2==0 || KEY_3==0)
- {
- delayMS(20); //20毫秒軟件防抖
- if (KEY_1 == 0)
- {
- keyValue = 1;
- while(KEY_1==0)
- {
- modifyTime(status+8);
- delayShow(500);
- }
- }
- if (KEY_2 == 0)
- {
- keyValue = 2;
- while(KEY_2==0)
- {
- modifyTime(status+16);
- delayShow(500);
- }
- }
- if (KEY_3 == 0)
- {
- keyValue = 3;
- }
- }
- }
- /*************按鈕響應處理函數******************************/
- void keyHandle()
- {
- if(keyValue==1)
- {
- DS1302_Write(sec,min,hour,day,month,week,year);
- keyValue = 0;
- }
- else if(keyValue==2)
- {
- DS1302_Write(sec,min,hour,day,month,week,year);
- keyValue = 0;
- }
- else if(keyValue==3)
- {
- if (status==1)
- {
- status = 2;
- }
- else if(status==2)
- {
- status = 3;
- }
- else if(status==3)
- {
- status = 1;
- }
- keyValue = 0;
- }
- }
復制代碼
還有修改時間的一些詭異邏輯代碼,涉及到一些標志變量,請仔細研讀體會:- /*************修改時間函數******************************/
- void modifyTime(int mode) //mode指明修改小時或分鐘 1:小時 2:分鐘
- {
- //修改小時(1)+遞增(8)
- if(mode == 9)
- {
- if(hour==0x23)
- {
- hour = 0x00;
- }
- else if(hour==0x09)
- {
- hour=0x10;
- }
- else if(hour==0x19)
- {
- hour=0x20;
- }
- else
- {
- hour=hour+0x01;
- }
- timeConvert();
- convertShow(hour_1,hour_2,min_1,min_2);
- }
- //修改小時(1)+遞減(16)
- if(mode == 17)
- {
- if(hour==0x00)
- {
- hour = 0x23;
- }
- else if(hour==0x10)
- {
- hour = 0x09;
- }
- else if(hour==0x20)
- {
- hour = 0x19;
- }
- else
- {
- hour = hour-0x01;
- }
- timeConvert();
- convertShow(hour_1,hour_2,min_1,min_2);
- }
- //修改分鐘(2)+遞增(8)
- if(mode == 10)
- {
- if(min==0x59)
- {
- min=0x00;
- }
- else if(min-(min_1<<4)==0x09)
- {
- min=(min_1+0x01)<<4;
- }
- else
- {
- min=min+0x01;
- }
- timeConvert();
- convertShow(hour_1,hour_2,min_1,min_2);
- }
- //修改分鐘(2)+遞減(16)
- if(mode == 18)
- {
- if(min==0x00)
- {
- min=0x59;
- }
- else if(min_2==0x00)
- {
- min=min-0x10;
- min=min+0x09;
- }
- else
- {
- min=min-0x01;
- }
- timeConvert();
- convertShow(hour_1,hour_2,min_1,min_2);
- }
- }
復制代碼
整體邏輯各部分的邏輯設計都完成了,我們現在開始設計整個程序的主函數部分。單片機上電后首先初始化(包括引腳置低什么的不再贅述)檢測DS1302是否在運行(內置電池可以掉電走時),如果在運行就讀取時間送顯,不在運行就起振(開始走時)。然后在每個顯示函數過后偵測按鈕操作,如果發現有效按鈕操作就進行處理按鈕的邏輯,該修改時間就修改時間,該顯示溫度就顯示溫度。這個流程用死循環加以嵌套,就可以無止無休的運行下去(不斷電的話)。下面是主函數代碼: - void main()
- {
- init();
- while(1)
- {
- if(status==3)
- {
- temp = DS18B20_ReadTemp();
- tempHandle();
- tempshow(temp_1,temp_2);
- }
- else
- {
- DS1302_readtime();
- convertShow(hour_1,hour_2,min_1,min_2);
- }
- keyScan();
- if(keyValue!=0&&KEY_1==1&&KEY_2==1&&KEY_3==1)
- {
- keyHandle();
- }
- }
- }
復制代碼
下面是初始化函數:- void init()
- {
- //關閉所有小燈
- E1=1;
- E2=1;
- E3=1;
- E4=1;
- MDLIGHT = 1;
- P1 = allclear;
- T_CE = 0;
- T_SCLK = 0;
- //默認初始化時間12:00
- sec = 0x00;
- min = 0x00;
- hour = 0x16;
- year = 0x01;
- month = 0x01;
- week = 0x01;
- day = 0x01;
- status = 1;
- keyValue = 0;
- delayMS(1000);
- //DS1302初始化判斷是否存在后備電源
- if(DS1302_Read(0x81)&0x80==0x80)
- {
- DS1302_Write_one(0x8e,0x00);
- DS1302_Write_one(0x80,sec); //起振
- DS1302_Write_one(0x8e,0x80);
- }
- else
- {
- }
- }
復制代碼
下面附上DS1302類庫,親測好用:- /*************寫入一字節****************/
- void DS1302_Input_Byte(char Input) //向時鐘IC寫入一字節
- {
- char i;
- T_SCLK = 0;
- delay2us();
- ACC =Input;
- for(i=8; i>0; i--)
- {
- T_DIO = ACC_0; //相當于匯編中的 RRC
- delay2us();
- T_SCLK = 1;
- delay2us();
- T_SCLK = 0;
- ACC = ACC >> 1;
- }
- }
-
- /*************讀取一字節****************/
- char DS1302_Output_Byte(void) //從時鐘IC讀取一字節()
- {
- char i;
- for(i=8; i>0; i--)
- {
- ACC>>=1;
- T_DIO= 1;
- delay2us();
- ACC_7 = T_DIO;
- T_SCLK = 1; //相當于匯編中的 RRC
- delay2us();
- T_SCLK = 0;
- delay2us();
- }
- T_DIO = 0;
- delay2us();
- return(ACC);
- }
-
- /*************寫一字節數據****************/
- void DS1302_Write_one( char addr,dat ) // 寫入地址、數據子程序
- {
- T_CE=0; //T_CE引腳為低,數據傳送中止
- T_SCLK=0; //清零時鐘總線
- T_CE = 1; //T_CE引腳為高,邏輯控制有效
- DS1302_Input_Byte(addr); // 地址,命令
- DS1302_Input_Byte(dat); // 寫1Byte數據
- T_SCLK = 1;
- T_CE = 0;
- }
-
- /*************讀一字節數據****************/
- char DS1302_Read ( char addr ) //數據讀取子程序
- {
- char date;
- T_CE=0;
- T_SCLK=0;
- T_CE = 1;
- DS1302_Input_Byte(addr); // 地址,命令
- date = DS1302_Output_Byte(); // 讀1Byte數據
- T_SCLK = 1;
- T_CE = 0;
- return(date);
- }
-
-
- /*************寫入時間數據****************/
- void DS1302_Write(char sec_w,min_w,hour_w,day_w,month_w,week_w,year_w)
- {
- DS1302_Write_one(0x8e,0x00);
- DS1302_Write_one(0x82,min_w);
- DS1302_Write_one(0x84,hour_w);
- DS1302_Write_one(0x86,day_w);
- DS1302_Write_one(0x88,month_w);
- DS1302_Write_one(0x8a,week_w);
- DS1302_Write_one(0x8c,year_w);
- DS1302_Write_one(0x80,sec_w);
- DS1302_Write_one(0x8e,0x80);
-
- }
-
- /*************時間轉換為顯示格式****************/
- void timeConvert()
- {
- sec_1 = sec>>4;
- sec_2 = sec&0x0f;
- min_1 = min>>4;
- min_2 = min&0x0f;
- hour_1 = hour>>4;
- hour_2 = hour&0x0f;
-
- }
-
- /*************從芯片讀取時間****************/
- void DS1302_readtime()
- {
- sec=DS1302_Read(0x81); //讀秒
- min=DS1302_Read(0x83); //讀分
- hour=DS1302_Read(0x85); //讀時
- day=DS1302_Read(0x87); //讀日
- month=DS1302_Read(0x89); //讀月
- year=DS1302_Read(0x8d); //讀年
- week=DS1302_Read(0x8b); //讀星期
- timeConvert();
-
- }
復制代碼
DIY教程Windows1.克隆或下載本倉庫,PCB電路圖在倉庫內,印刷后按照引腳焊接元件。 2.下載宏晶科技官網所提供的相關燒錄軟件與教程,并安裝。 3.下載KeilC51開發工具,并安裝。 4.下載TKStudio,并安裝(可選)。 5.使用USB轉TTl燒錄器連接板載串口與計算機(如果需要驅動請自行安裝) 6.使用STC燒錄軟件,選擇STC15W402AS型號,使用默認配置(單片機震蕩頻率11.0592MHz),載入想要燒錄的二進制文件,上電燒錄。 7.如果需要增加修改邏輯代碼,可以使用TKStudio打開main-code/Clock.xmp進行二次開發,其他IDE也可。 最后附上代碼以及PCB:
0.png (46.17 KB, 下載次數: 71)
下載附件
2018-5-7 17:44 上傳
0.png (5.37 KB, 下載次數: 84)
下載附件
2018-5-7 17:45 上傳
全部資料51hei下載地址:
ds1302-stc15-clock-master.zip
(184.78 KB, 下載次數: 73)
2018-5-7 17:39 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|