程式期末競試--電子時鐘 通訊一甲 B09622048 楊穎穆
目錄 目的 我的時鐘功能 設計原理 流程圖 程式 實驗結果 資料來源 結論
目的 使用C語言設計製作一時鐘。 時鐘最基本功能須具備下列功能: a. 顯示時、分、秒功能。 b. 具有時、分校正之功能。 附加功能: a. 具有年、月、日、星期顯示與校正者。 b. 具有中國農曆年、月、日、星期顯示與校正設定者。 c. 正點報時功能者。 d. 單組定時ON與定時OFF顯示與校正設定者。 e. 多組定時ON與定時OFF顯示與校正設定者。 f. 具小睡顯示與校正設定者。 g. 具Radio Calibration者。 h. 具GPS Calibration者。 i. 具Internet Calibration者。 j. 具溫度顯示者。 k. 具溼度顯示者。 l. 具CO2、CO1濃度顯示與警告功能者。 第2項:專題論文+投影片(PPT檔)+影音檔+網頁: a. 專題論文格式按一般會議論文兩列格式中文撰寫,圖、表格必須清楚,使用之參考資料也必須詳列。 b. 投影片(PPT檔)必須將您所設計製作的動機、原理、特色、貢獻與結論,摘錄成Power Point檔。 c. 影音檔:使用Camtasia將以上投影片、作品製作過程及作品操作使用錄製成影音檔(AVI格式)。 d. 網頁:將以上所有製成網頁安置在系學生園地供人瀏覽外,另燒錄成CD片(容量盡可能在500M以下)
我的時鐘功能 二十四小時制。 顯示時、分、秒功能。 能顯示上、下午功能。 具有校正功能。
設計原理 設定計時計數模式 允許計時計數中斷 設定計時計數內之計數值 啟動計數 時間到,跳到計時計數中斷副程式,去 處理後續工作 後續工作完成後,則自動回主程式
設計原理 中斷允許暫存器:IE( Interrupt Enable Registor) EA ET2 ES ET1 EX1 ET0 EX0 1 0 0 0 0 0 1 0 IE=10000010=0x82 供計時計數允許中斷Timer0 EA ET2 ES ET1 EX1 ET0 EX0 IE 可由各自的中斷 允許位元來設定 供計時計數 允許中斷 Timer1 供INT0允許 中斷用 供INT1允許 中斷用
設計原理 0 0 :13bit計數方式 0 1 :16bit計數方式 1 0 :8bit重新載入模式 1 1 : 特殊模式 TMOD=00000010=0x02 0 0 0 0 0 0 1 0 TMOD Gate C/〒 M1 M0 Timer1 Timer0 ※ M1,M0:模式 0 0 :13bit計數方式 0 1 :16bit計數方式 1 0 :8bit重新載入模式 1 1 : 特殊模式 ※ C/〒 : 0 計時器,1 計數器 ※ Gate=0,TR=0 :停止計時計數 Gate=0,TR=1 :開始計時計數
設計原理 中斷優先暫存器IP (Interrupt Priority register)中有一位元來決定中斷副程式被執行的優先順序,假如設定為〝1〞表示為高優先權,〝0〞則表示為低優先權。 INT0 EA 高 優 先 權 IE0 EX0 低 優 先 權 EA ET0 TF0 INT1 EX1 IE0 EA EA ET1 TF1 T1 R1 EA ES EA ET2 TF2 EXF2
設計原理 我們所使用的是”8bit重新載入模式”,所以在設定上8bit為2的八次方=256,它的初始值=200。 TL0=256-200=56; TH0=256-200=56。
流 程 圖(主程式) main 初始值 Yes 校正change() 校正change() No 時鐘計時 顯示show()
流 程 圖(中斷&時鐘計時計數副程式) No Yes No Yes No Yes No Yes timer0() hs==0 hs-- return Yes s--; hs==2304 No s==0 Yes s=2 No t[0]==9 t[0]=t[0]+1 return Yes t[0]=0 No t[1]==5 t[1]=t[1]+1 return Yes t[1]=0 1
流 程 圖(中斷&時鐘計時計數副程式) No Yes No Yes No No No Yes Yes Yes 1 return t[2]=t[2]+1 Yes t[2]=0 No t[3]==5 t[3]=t[3]+1 return Yes t[3]=0 No No t[4]==3&& t[5]==2 t[4]==9 No t[4]=t[4]+1 Yes Yes t[4]=0 t[4]==2&& t[5]==1 t[4]=0; t[5]=0; t[6]=10; t[7]=11; Yes t[5]++ t[6]=10; t[7]=12; return return return
流 程 圖(校正副程式) No Yes No No Yes Yes No Yes No Yes change() P3_7==1 TR0=1 return Yes TR0=0 No k==8 P3_6==1 No Yes Yes k=0 No w++ w==200 w=0 Yes show() P3_6==0 No b=P0&0x0F Yes k++ t[k]=b return
流 程 圖(顯示副程式) Yes No Show() P1=0xFF; P2=bcd2seg[t[i]]; P1=~scan; scan=scan<<1; i++; Yes i==8; i=0; scan=0x01; return No
程 式 #include"reg51.h" //函式庫 sfr P4 = 0xD8; //判斷是否進入燒錄模式 sbit P4_3 = P4^3; //判斷是否進入燒錄模式 int hs=2304; //宣告變數 hs=2304 int s=2,k=0,w=0; //宣告變數 s=2,k=0,w=0; int scan=0x01,i=0; //宣告變數 scan=1,i=0 unsigned char code bcd2seg[ ]={0x81,0xCF,0x92,0x86,0xCC, 0xA4,0xA0,0x8F,0x80,0x84,0xFE,0x88,0x98}; //宣告七段顯示陣列 unsigned char t[8]={0,0,0,0,0,0,10,11}; //宣告陣列 t 及其初始值設定 void show(void); //宣告副程式 show void change(void); //宣告副程式 change sbit P3_6=P3^6; //宣告腳位P36 sbit P3_7=P3^7; //宣告腳位P37
程 式(主程式) int main(void){ //主程式開始 void (*isp) (void) = 0xf800; //判斷是否進入燒錄模式 if(P4_3==0) (*isp) (); //判斷是否進入燒錄模式 TMOD=0x02; //計時計數模式 IP=0; //允許計時計數中斷 IE=0x82; //允許計時計數中斷 TL0=56; //(256-200)=56 TH0=56; //(256-200)=56 while(1){ //開始執行動作 change(); //呼叫校正副程式 change show(); //呼叫顯示副程式 show }
程 式(中斷&時鐘計時計數副程式) void timer0(void) interrupt 1{ //中斷&計時計數副程式 if(hs==0){ //假如我hs=0,s值會減1 s--; if(s==0){ //假如s=0,s=2 s=2; if(t[0]==9){ t[0]=0; //假如當陣列t[0]計數到為9時,t[0]的下一狀態就會顯示為0 if(t[1]==5){ t[1]=0; //假如當陣列t[1]計數到為5時,t[1]的下一狀態就會顯示為0 if(t[2]==9){ t[2]=0; //假如當陣列t[2]計數到為9時,t[2]的下一狀態就會顯示為0 if(t[3]==5){ t[3]=0; //假如當陣列t[3]計數到為9時,t[3]的下一狀態就會顯示為0 if(t[4]==3 && t[5]==2){ t[4]=0; t[5]=0; t[6]=10; t[7]=11; //假如當陣列t[4]計數到為3時,且t[5]計數到為2時,t[4],t[5] 的下一狀態就會顯示為0,t[6]會顯示為 -,t[7]會顯示為 A }
程 式(中斷&時鐘計時計數副程式) else{ if(t[4]==9){ t[4]=0; t[5]++; } else t[4]++; //否則t[4]加1持續計數 if(t[4]==2 && t[5]==1){ t[6]=10; t[7]=12; //假如當陣列t[4]計數到為2時,且t[5]計數到為1時,t[6]會顯示為 -,t[7]會顯示為 p } else t[3]++; //否則t[3]持續加1計數 else t[2]++; //否則t[2]持續加1計數 else t[1]++; //否則t[1]持續加1計數 else t[0]++; //否則t[0]持續加1計數 hs=2304; //執行半秒所需的時間 else hs--; }`
程 式(校正副程式) void change(void){ int b; if(P3_7==1){ //假如當我P3_7為1時TR0=0停止計數 TR0=0; if(P3_6==1){ //假如當我P3_6為1時,w值加1 w++; while(w==200){ //當我w為200時,會在迴圈內一直執行動作 if(P3_6==0){ //假如當我P3_6為0,k值會持續加1 k++; if(k==8){ //假如k值已經為8,k會從陣列第一個位置從頭開始 k=0; } w=0; //w 值從0開始 } show( ); //呼叫顯示副程式,將我們調整後的值顯示出來 b=P0&0x0F; //輸入的值以後四位來控制 t[k]=b; //當我調到我要的陣列位置顯示出來的值為我輸入的b值 else TR0=1; //否則我開始計數
程 式(顯示副程式) void show(void){ //副程式 show開始執行 P1=0xFF; //遮沒 P2=bcd2seg[t[i]]; //顯示七段顯示 P1=~scan; //由第一個七段開始顯示 scan=scan<<1; //向左位移一位 i++; // i值加1 if(i==8){ i=0; scan=0x01; } //判別 i是否已經為 8,"是"i會為 0,scan=1 }
實驗結果(1) 時鐘顯示 位移陣列位址 判別是否進入校正 我的輸入值
實驗結果(2)
實驗結果(3)
資料來源 王志湖老師上課教授的內容所做成的筆記。 同學間討論的結果。
結論 可透過這次電子鐘的實驗,讓我有進一步的了解,也學習到更多,雖在一些地方不是很完美,像是在校正部分必須要靠開關各別去輸入我想要的數值就有點麻煩,所以在這方面是需要去改進的。
END