電子時鐘實訓報告
一, 實訓目的 二,實訓要求 三,實訓基本原理 四,實訓設計分析 五,實訓要求實現 A.電路設計 1. 整體設計 2. 分塊設計 B.程序設計 1 程序總體設計 2全部完整代碼: 六.實訓總結及感想
一,實訓目的 20世紀末,電子技術獲得了飛速的發展,在其推動下,現代電子產品幾乎滲透了社會的各個領域,有力地推動了社會生產力的發展和社會信息化程度的提高,同時也使現代電子產品性能進一步提高,產品更新換代的節奏也越來越快。 現代生活的人們越來越重視起了時間觀念,可以說是時間和金錢劃上了等號。對于那些對時間把握非常嚴格和準確的人或事來說,時間的不準確會帶來非常大的麻煩,所以電子鐘是以其小巧,價格低廉,走時精度高,使用方便,功能多,便于集成化而受廣大消費的喜愛,得到了廣泛的使用。 1. 學習8051定時器時間計時處理、按鍵掃描及LCD液晶顯示的設計方法。 2. 設計任務及要求 利用實訓平臺上LCD1602液晶顯示屏, 設計帶有鬧鈴功能的數字時鐘
二,實訓要求
A.基本要求: 1. 在LCD1602液晶顯示屏上顯示當前日期,時間。 2. 利用按鍵可對時間及鬧玲進行設置,并可顯示設置鬧玲的時間。鬧玲時間到蜂鳴器發出聲響,一分鐘后鬧鈴停止。
B.擴展部分: 1.日歷功能(能對年,月,日,星期進行顯示,分辨平年,閏年以及各月天數,并調整)實現年月日時分秒的調整,星期準確的隨著日期改變而改變進行顯示。 2.定時功能(設定一段時間長度,定時到后,鬧鈴提示)
C.可擴展部分: 1.鬧鈴重響功能(鬧鈴被停止后,以停止時刻開始,一段時間后鬧鈴重響,且重響時間的間隔可調) 2.可進行備忘錄提示,按照年月日,可在設定的某年某月進行鬧鈴提示。
三,實訓基本原理
四,實訓設計分析 針對要實現的功能,采用AT89S52單片機進行設計,AT89S52 單片機是一款低功耗,高性能CMOS8位單片機,片內含4KB在線可編程(ISP)的可反復擦寫1000次的Flash只讀程序存儲器,器件采用高密度、非易失性存儲技術制造,兼容標準MCS- 51指令系統及80C51引腳結構。這樣,既能做到經濟合理又能實現預期的功能。 在程序方面,采用分塊設計的方法,這樣既減小了編程難度、使程序易于理解,又能便于添加各項功能。程序可分為鬧鐘的聲音程序、時間顯示程序、日期顯示程序,秒表顯示程序,時間調整程序、鬧鐘調整程序、定時調整程序,延時程序等。運用這種方法,關鍵在于各模塊的兼容和配合,若各模塊不匹配會出現意想不到的錯誤。 首先,在編程之前必須了解硬件結構尤其是各引腳的用法,以及內部寄存器、存儲單元的用法,否則,編程無從下手,電路也無法設計。這是前期準備工作。第二部分是硬件部分:依據想要的功能分塊設計設計,比如輸入需要開關電路,輸出需要顯示驅動電路和數碼管電路等。第三部分是軟件部分:先學習理解C語言的編程方法再根據設計的硬件電路進行分塊的編程調試,最終完成程序設計。第四部分是軟件畫圖部分:設計好電路后進行畫圖,包括電路圖和仿真圖的繪制。第五部分是軟件仿真部分:軟硬件設計好后將軟件載入芯片中進行仿真,仿真無法完成時檢查軟件程序和硬件電路并進行修改直到仿真成功。第六部分是硬件實現部分:連接電路并導入程序檢查電路,若與設計的完全一樣一般能實現想要的功能。最后進行功能擴展,在已經正確的設計基礎上,添加額外的功能! 五,實訓要求實現 A.電路設計 1. 整體設計 此次設計主要是應用單片機來設計電子時鐘,硬件部分主要分以下電路模塊:顯示電路用lcd1602顯示,年份,月份,星期,小時、分鐘和秒(日),使電路更加簡單。單片機采用AT89S51系列,這種單片機應用簡單,適合電子鐘設計。 電路的總體設計框架如下: 
2. 分塊設計 模塊電路主要分為:復位電路、按鍵、LCD和時鐘芯片。 2.1 按鍵處理模塊 
按鍵處理設置為:如沒有按鍵,則時鐘正常走時。當按K0鍵一次,時鐘暫停走動進入調小時狀態,再按K0鍵一次,進入調分狀態,再按K0鍵一次,回到正常走時;對于K1和K2按鍵,如果是正常走時,按K1和K2不起作用,如果進入調時或調分狀態,按K1可對時或分進行加1操作,小時加到24則回到0,分加到60則回到0;按K2可對時或分進行減1操作,小時減到負則回到23,分減到負則回到59。按鍵處理模塊流程如圖所示。  2.2 輸出部分 本電路的輸出信號LCD的寫入命令和寫入數據,鬧鈴脈沖信號。 鬧鈴由P1.5端輸出,模塊如下: 
日期時間由LCD1602輸出,模塊如下: 
2.3 晶振與復位電路 本實訓單片機時鐘用內部時鐘,模塊如下: 
復位電路為手動復位構成,模塊如下: 
B.程序設計 B.1 程序總體設計 軟件程序劃分為以下幾個部分:系統主程序、DS1302驅動程序、LCD驅動程序。在主程序中調用DS1302驅動程序和LCD驅動程序,另外在主程序中還包含按鍵處理。 主程序先是將LCD初始化,其次在LCD顯示日期和時間的提示信息,然后進入死循環,在循環中先判斷是否有鍵按下,如按下K0鍵,則功能單元加1;如按下K1鍵,則根據功能單元的內容把日期時間相應位加1;如按下K2鍵,則根據功能單元的內容把日期時間相應位減1;并把修改后的日期時間寫入1302(在這個過程中注意日期時間的數據格式的轉換)。其次讀DS1302日歷時鐘寄存器,讀出的內容存入日期、時間緩沖區;最后把日期、時間緩沖區數轉化為ASCII碼放入LCD顯示緩沖區并調用LCD顯示程序顯示。 程序總的流程圖如下: 
C.硬件定時液晶顯示時鐘硬件電路
2.全部完整代碼: 基于STC89S51單片機以及液晶1602顯示的萬年歷項目
六.實訓總結及感想 時光飛逝,一轉眼,一個學期又進尾聲了,本學期的單片機綜合課程設計也在三周內完成了。
俗話說“好的開始是成功的一半”。說起課程設計,我認為最重要的就是做好設計的預習,認真的研究老師給的題目。其次,老師對實驗的講解要認真聽講,把資料認真看懂,因為只有都明白了,做起設計就會事半功倍,如果沒弄明白,就迷迷糊糊的去做設計,到頭來一點收獲也沒有。最后,最重要的是要重視程序的模塊化,能看懂程序,在此基礎上擴展功能,也要注重程序的調試,掌握其方法。
雖然這次的課程設計算起來在實驗室的時間只有六個課時,不過在宿舍里查資料,看資料,做實驗的時間一定不止六個課時。
硬件的設計跟焊接都要我們自己動手去焊,軟件的編程也要我們不斷的調試,最終一個能完成課程設計的勞動成果出來了,很高興它能按著設計的思想與要求運動起來。
當然,這其中也有很多問題,第一、不夠細心比如由于粗心大意焊錯了線,由于對課本理論的不熟悉導致編程出現錯誤。第二,是在學習態度上,這次課設是對我的學習態度的一次檢驗。對于這次單片機綜合課程實習,我的第一大心得體會就是作為一名工程技術人員,要求具備的首要素質絕對應該是嚴謹。我們這次實習所遇到的多半問題多數都是由于我們不夠嚴謹。第三,在做人上,我認識到,無論做什么事情,只要你足夠堅強,有足夠的毅力與決心,有足夠的挑戰困難的勇氣,就沒有什么辦不到的。 我們組一起完成了這次單片機課程設計課題中的電子時鐘設計,從中學到很多東西,如何從理論到實踐中的轉化,怎樣將所學的知識運用到實踐當中,運用到現實生活當中,此次的課堂設計給我奠定了基礎,我會在以后的工作學習中磨練自己,使自己適合于以后的競爭,同時在查找資料的過程中學到許多新的知識, 在和同學合作的過程中增進友誼,一個團隊合作的重要性,也是使我對團隊精神的積極進取性與重要性有了更加充分的理解。 最后,感謝老師的一個學期對我們的教育,正是老師的精彩課程和對我們嚴格的要求,老師熱心的幫助,使得我們課程設計能夠順利的完成,同時在課程設計的過程中鞏固我們的單片機知識,相信對我以后的工作會有很大的幫助!
單片機源程序如下: - #include <reg51.h>
- #include <absacc.h> //定義絕對地址訪問
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit T_CLK = P1^3; //DS1302時鐘線引腳
- sbit T_IO = P1^4; //DS1302數據線引腳
- sbit T_RST = P1^2; //DS1302復位線引腳
- sbit RS=P1^7; //定義LCD的控制線
- sbit RW=P1^6;
- sbit EN=P1^5;
- sbit key0=P3^0; //定義按鍵
- sbit key1=P3^1;
- sbit key2=P3^2;
- sbit ACC7 =ACC^7;
- sbit ACC0 =ACC^0;
- char line1[]="LCD test program";
- char line2[]="Everything is OK";
- char line3[]="Welcome to you ";
- char line4[]="Welcome to using";
- void init_LCD(void);
- void write_inst(char); // 寫入指令函數
- void write_char(char); // 寫入字元函數
- void check_BF(void); // 檢查忙碌函數
- void delay1ms(int);
- uchar datechar[]={"DATE:"};
- uchar timechar[]={"TIME:"};
- uchar datebuffer[8]={0,0,0x2d,0,0,0x2d,0,0}; //定義日歷顯示緩沖區
- uchar timebuffer[8]={0,0,0x3a,0,0,0x3a,0,0}; //定義時間顯示緩沖區
- uchar data ttime[3]={0x00,0x00,0x00}; //分別為秒、分和小時的值
- uchar data tdata[3]={0x00,0x00,0x00}; //分別為年、月、日
- //往DS1302寫入1Byte數據
- void WriteB(uchar ucDa)
- {
- uchar i;
- ACC = ucDa;
- for(i=8; i>0; i--)
- {
- T_IO = ACC0; //相當于匯編中的 RRC
- T_CLK = 1;
- T_CLK = 0;
- ACC = ACC >> 1;
- }
- }
- //從DS1302讀取1Byte數據
- uchar ReadB(void)
- {
- uchar i;
- for(i=8; i>0; i--)
- {
- ACC = ACC >>1;
- ACC7 = T_IO;T_CLK = 1;T_CLK = 0; //相當于匯編中的 RRC
- }
- return(ACC);
- }
- //DS1302單字節寫,向指定單元寫命令/數據,ucAddr: DS1302地址, ucDa: 要寫的命令/數據
- void v_W1302(uchar ucAddr,uchar ucDa)
- {
- T_RST = 0;
- T_CLK = 0;
- _nop_();_nop_();
- T_RST = 1;
- _nop_();_nop_();
- WriteB(ucAddr); /* 地址,命令 */
- WriteB(ucDa); /* 寫1Byte數據*/
- T_CLK = 1;
- T_RST =0;
- }
- //DS1302單字節讀,從指定地址單元讀出的數據
- uchar uc_R1302(uchar ucAddr)
- {
- uchar ucDa=0;
- T_RST = 0;T_CLK = 0;
- T_RST = 1;
- WriteB(ucAddr); /*寫地址*/
- ucDa = ReadB(); /*讀1Byte命令/數據 */
- T_CLK = 1;T_RST =0;
- return(ucDa);
- }
- //LCD檢查忙函數
- void fbusy()
- {
- P2 = 0xff;
- RS = 0;
- RW = 1;
- EN = 1;
- EN = 0;
- while((P2 & 0x80))
- {
- EN = 0;
- EN = 1;
- }
- }
- //LCD寫命令函數
- void wc51r(uchar j)
- {
- fbusy();
- EN = 0;
- RS = 0;
- RW = 0;
- EN = 1;
- P2 = j;
- EN = 0;
- }
- //LCD寫數據函數
- void wc51ddr(uchar j)
- {
- fbusy(); //讀狀態;
- EN = 0;
- RS = 1;
- RW = 0;
- EN = 1;
- P2 = j;
- EN = 0;
- }
- void init() //LCD1602初始化
- {
- while(1)
- { //指定第一行位置
- write_inst(0x80);
- for(j=0;j<16;j++)
- write_char(line1[j]); //循環顯示16個字符
- write_inst(0xc0); //指定第二行位置
- for(j=0;j<16;j++)
- write_char(line2[j]); //循環顯示16個字符
- delay1ms(2000); //延時2s (STC89C51:2000)(MPC82G516:20000)
- write_inst(0x80);
- for(j=0;j<16;j++)
- write_char(line3[j]);
- write_inst(0xc0);
- for(j=0;j<16;j++)
- write_char(line4[j]);
- delay1ms(2000);
- }
- }
- void init_LCD(void)
- {
- write_inst(0x38); //指令6:設定兩行
- //write_inst(0x08); //指令4:關閉顯示
- wc51r(0x01); //清屏
- wc51r(0x38); //使用8位數據,顯示兩行,使用5*7的字型
- wc51r(0x0c); //顯示器開,光標開,字符不閃爍
- wc51r(0x06); //字符不動,光標自動右移一格
- }
- //************延時函數************
- void delay(uint i) //延時函數
- {uint y,j;
- for (j=0;j<i;j++){
- for (y=0;y<0xff;y++){;}}
- }
- void main(void)
- {
- uchar i,set;
- uchar data temp;
- SP=0X50;
- delay(10);
- init();
- wc51r(0x80);
-
- for (i=0;i<5;i++) wc51ddr(datechar[i]); //第一行開始顯示DATA:
- wc51r(0xc0);
- for (i=0;i<5;i++) wc51ddr(timechar[i]); //第二行開始顯示TIME:
- while(1)
- {P3=0XFF;
- if(key0==0) { delay(10);if (key0==0) { while (key0==0); set++; if
- (set==6) set=0;}}
- if(key1==0) { delay(10); //如果是加1鍵,則日歷、時鐘相應位加1
- if (key1==0) { while (key1==0);
- switch(set)
- {
- case 1: tdata[0]++;if (tdata[0]==100) tdata[0]=0;
- temp=(tdata[0]/10)*16+tdata[0]%10;
- v_W1302(0x8e,0);
- v_W1302(0x8c,temp);
- v_W1302(0x8e,0x80);
- break;
- case 2: tdata[1]++;if (tdata[1]==13) tdata[1]=1;
- temp=(tdata[1]/10)*16+tdata[1]%10;
- v_W1302(0x8e,0);
- v_W1302(0x88,temp);
- v_W1302(0x8e,0x80);
- break;
- case 3: tdata[2]++;if (tdata[2]==32) tdata[2]=1;
- temp=(tdata[2]/10)*16+tdata[2]%10;
- v_W1302(0x8e,0);
- v_W1302(0x86,temp);
- v_W1302(0x8e,0x80);
- break;
- case 4: ttime[2]++;if (ttime[2]==24) ttime[2]=0;
- temp=(ttime[2]/10)*16+ttime[2]%10;
- v_W1302(0x8e,0);
- v_W1302(0x84,temp);
- v_W1302(0x8e,0x80);
- break;
- case 5: ttime[1]++;if (ttime[1]==60) ttime[1]=0;
- temp=(ttime[1]/10)*16+ttime[1]%10;
- v_W1302(0x8e,0);
- v_W1302(0x82,temp);
- v_W1302(0x8e,0x80);
- break;
- }
- }
- }
- if(key2==0) { delay(10); //如果是減1鍵,則日歷、時鐘相應位減1
- if (key2==0) { while (key2==0);
- switch(set)
- {
- case 1: tdata[0]--;if (tdata[0]==0xff) tdata[0]=99;
- temp=(tdata[0]/10)*16+tdata[0]%10;
- v_W1302(0x8e,0);
- v_W1302(0x8c,temp);
- v_W1302(0x8e,0x80);
- break;
- case 2: tdata[1]--;if (tdata[1]==0x00) tdata[1]=12;
- temp=(tdata[1]/10)*16+tdata[1]%10;
- v_W1302(0x8e,0);
- v_W1302(0x88,temp);
- v_W1302(0x8e,0x80);
- break;
- case 3: tdata[2]--;if (tdata[2]==0x00) tdata[2]=31;
- temp=(tdata[2]/10)*16+tdata[2]%10;
- v_W1302(0x8e,0);
- v_W1302(0x86,temp);
- v_W1302(0x8e,0x80);
- break;
- case 4: ttime[2]--;if (ttime[2]==0xff) ttime[2]=23;
- temp=(ttime[2]/10)*16+ttime[2]%10;
- v_W1302(0x8e,0);
- v_W1302(0x84,temp);
- v_W1302(0x8e,0x80);
- break;
- case 5: ttime[1]--;if (ttime[1]==0xff) ttime[1]=59;
- temp=(ttime[1]/10)*16+ttime[1]%10;
- v_W1302(0x8e,0);
- v_W1302(0x82,temp);
- v_W1302(0x8e,0x80);
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
0.png (47.03 KB, 下載次數: 41)
下載附件
2018-9-21 17:13 上傳
|