# 數位式時鐘設計 ## 實驗材料: 電阻,開關,pmos,七段顯示器,Arduino uno ## 實驗方法: #### 3-3 1. P11A-7~P11A-1連接到13腳 2. P11B-4~P11B-1連接到5~2腳 3. P5-1(指撥開關)連接A0 4. P11B-5連接A1 5. P6-5~P6-8連到A2~A5,而P6接地 ## 程式碼 3-7 ```c= const int SEG[7] = {6,7,8,9,10,11,12}; // 宣告顯示信號接腳 const int scan[4] = {2,3,4,5}; // 宣告掃描信號接腳(scan) const int SEG_code[10] = { // 宣告七段顯示碼陣列 0xc0,0xf9,0xa4,0xb0,0x99, // 0~4 0x92,0x82,0xf8,0x80,0x90 } ; // 5~9 const int PB[4]={A2,A3,A4,A5}; // 按鍵, 小時(兩位數)與分鐘(兩位數) const int DD=A1; // 閃秒LED const int DIPSW=A0; // 指撥開關 const int BZ=13; // 蜂鳴器 int disp[4]={0,0,0,0}; // 宣告顯示緩衝區陣列 int DISP; // 宣告顯示變數 unsigned long x0,x1,x2; // 宣告時間變數 // 宣告狀態旗標:phase0 = false計時模式(ON), // phase0 = true調整模式(OFF) boolean phase0; int seconds=0,sec=0; // 宣告秒變數 // 函式原型 void beep(int pin, int counts); // 宣告嗶聲函數 void scanner(int x); // 宣告掃描函數 // 初始設定 void setup() { for(int i=0;i<7;i++) pinMode(SEG[i], OUTPUT); // 設定顯示信號接腳為輸出接腳 for(int i=0;i<4;i++) { pinMode(scan[i], OUTPUT); // 設定顯示掃描接腳為輸出接腳 pinMode(PB[i], INPUT); // 設定PB(行接腳)為輸入接腳 } pinMode(DD, OUTPUT); // 設定閃秒LED接腳為輸出接腳 pinMode(BZ, OUTPUT); // 設定蜂鳴器接腳為輸出接腳 pinMode(DIPSW, INPUT); // 設定指撥開關接腳為輸入接腳 } // 主程式 void loop() { if (digitalRead(DIPSW)) phase0=true; //狀態設定,讀取指撥開關=1:調整模式 else phase0=false; //狀態設定,讀取指撥開關=0:計時模式 //調整模式狀態 while(phase0) { seconds=0; //秒數歸零 //小時遞增調整,按鍵(4x4鍵盤) 為低態動作 if (!digitalRead(PB[0])) { //若PB[0]被按下(小時遞增) if (disp[3]==2 && disp[2]==2) { //若已達到22時 disp[3]=1; //小時之十位數歸零 disp[2]=2; //小時之個位數歸零 } else if (disp[2]==9) { //若小時之個位數等於9 disp[2]=0; //小時之個位數歸零 disp[3]++; //小時之十位數遞增(進位) } else disp[2]++; //否則小時之個位數遞增 } //小時遞減調整(按鍵為低態動作) if (!digitalRead(PB[1])) { //若PB[1]被按下(小時遞減) if (disp[3]==0 && disp[2]==0) { //若已00時 disp[3]=2; //小時之十位數調整為2 disp[2]=3; //小時之個位數調整為3 } else if (disp[2]==0) { //若小時之個位數等於0 disp[2]=9; //小時之個位調整為9 disp[3]--; //小時之十位數遞減(借位) } else disp[2]--; //否則小時之個位數遞減 } //分鐘遞增調整(按鍵為低態動作) if (!digitalRead(PB[2])) { //若PB[2]被按下(分鐘遞增) if (disp[1]==5 && disp[0]==9) { //若已59分 disp[1]=0; //分鐘之十位數歸零 disp[0]=0; //分鐘之個位數歸零 } else if (disp[0]==9) { //若分鐘之個位數等於9 disp[0]=0; //分鐘之個位數歸零 disp[1]++; //分鐘之十位數遞增(進位) } else disp[0]++; //否則分鐘之個位數遞增 } //分鐘遞減調整(按鍵為低態動作) if (!digitalRead(PB[3])) { //若PB[3]被按下(分鐘遞減) if (disp[1]==0 && disp[0]==0) { //若已00分 disp[1]=5; //分鐘之十位數調整為5 disp[0]=9; //分鐘之個位數調整為9 } else if (disp[0]==0) { //若分鐘之個位數等於0 disp[0]=9; //分鐘之個位調整為9 disp[1]--; //分鐘之十位數遞減(借位) } else disp[0]--; //否則分鐘之個位數遞減 } scanner(25); //連續掃描25週(100ms,每秒約10次) if (digitalRead(DIPSW)) phase0=true; //讀取指撥開關=1:調整模式 else phase0=false; //讀取指撥開關=0:計時模式 } //計時模式 while(!phase0) { scanner(2); //連續掃描2週(8ms) x1=millis(); //查詢時間 x2=x1-x0; //計算時間差 if (x2>=500) { //0.5秒時間差 x0=x1; //記錄時間 sec=!sec; //切換閃秒一直閃爍跳動 digitalWrite(DD,sec); //處理時間 //處理時間 if (sec) { //處理秒數 if (++seconds==60) { //秒數加1 seconds=0; //若秒數滿60則歸零 if (disp[0]==9) { //若分鐘之個位數滿9 disp[0]=0; //則分鐘之個位數歸零 if (disp[1]==5) { //若分鐘之十位數滿5 disp[1]=0; if (disp[2]==3 && disp[3]==2) { //若為23時 disp[2]=0; //則小時之個位數歸零 disp[3]=0; //則小時之十位數歸零 } else if (disp[2]==9) { //若小時之個位數滿9 disp[2]=0; //則小時之個位數歸零 disp[3]++; //小時之十位數加1 } else disp[2]++; //否則小時之個位數加1 } else disp[1]++; //否則分鐘之十位數加1 } else disp[0]++; //否則分鐘之個位數加1 } } } if (digitalRead(DIPSW)) phase0=true; //讀取指撥開關=1:調整模式 else phase0=false; //讀取指撥開關=0:計時模式 } } //七段顯示器掃描函式 void scanner(int x) { // G~A(不含小數點)每週期4ms for(int i=0;i<x;i++) { //重複掃描x次 for(int j=0;j<4;j++) { //掃描四位數 //關閉掃描信號(防殘影) for(int k=0;k<4;k++) digitalWrite(scan[k],1); //掃描信號為1111 //輸出七節顯示器顯示信號 DISP=SEG_code[disp[j]]; // 讀取顯示信號 for(int k=0;k<8;k++) { // 並列資料串列輸出 if(bitRead(DISP,k)) digitalWrite(SEG[k],1); else digitalWrite(SEG[k],0); } //輸出掃描信號 digitalWrite(scan[j],0); delay(1); //延遲1ms } } } // 嗶聲函數 void beep(int pin, int counts) { for(int i=0;i<counts;i++) { //執行counts次 tone(pin,1000,100); //發聲(1kHz,0.1秒) delay(100); //靜音(0.1秒) } } ``` ## 實驗結果 ![](https://i.imgur.com/bvG4ofn.png) disp[3]==2 && disp[2]==2) { //若已達到22時 disp[3]=1; //小時之十位數歸零 disp[2]=2; //小時之個位數歸零 ## 實驗心得 電路非常的複雜,但是做出來的時候很有成就感~~ 也對微處理機有更進一步的認識了