# 數位式時鐘設計
## 實驗材料:
電阻,開關,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秒)
}
}
```
## 實驗結果

disp[3]==2 && disp[2]==2) { //若已達到22時
disp[3]=1; //小時之十位數歸零
disp[2]=2; //小時之個位數歸零
## 實驗心得
電路非常的複雜,但是做出來的時候很有成就感~~
也對微處理機有更進一步的認識了