軟體架構 (裸機輪詢/中斷)
// 狀態機狀態
typedef enum { COUNT_A, COUNT_B, FLASH, RESET } State;
volatile uint8_t cntA = 0, cntB = 0;
volatile uint8_t flash_cnt = 0;
volatile State state = COUNT_A; // 簡化:主迴圈輪詢按鍵
// 按鍵消抖 + 邊緣偵測
bool key_pressed(volatile uint8_t *port, uint8_t pin) {
static uint8_t last[8] = {1};
uint8_t cur = (*port >> pin) & 1; // 假設低電平觸發
if (last[pin] == 1 && cur == 0) { last[pin] = 0; return true; }
if (cur == 1) last[pin] = 1;
return false;
}
// LED 顯示 (共陽/共陰視硬體調整)
void display(uint8_t val, uint8_t group) { // group 0:A, 1:B
// P1 低 4 位給 A 組,高 4 位給 B 組
if (group == 0) P1 = (P1 & 0xF0) | (val & 0x0F);
else P1 = (P1 & 0x0F) | ((val << 4) & 0xF0);
}
void delay_ms(uint16_t ms) { /* 定時器或空迴圈 */ }
int main() {
// IO 初始化: P1 輸出, P3 輸入上拉
while (1) {
if (state == COUNT_A || state == COUNT_B) {
if (key_pressed(&P3, 0)) { // 開關 A
if (++cntA > 15) cntA = 15;
display(cntA, 0);
if (cntA == 15) state = FLASH;
}
if (key_pressed(&P3, 1)) { // 開關 B
if (++cntB > 15) cntB = 15;
display(cntB, 1);
if (cntB == 15) state = FLASH;
}
} else if (state == FLASH) {
// 閃爍 3 秒 (約 30 次 100ms)
for (int i = 0; i < 30; i++) {
display(cntA==15 ? 0xF : 0, 0);
display(cntB==15 ? 0xF : 0, 1);
delay_ms(50);
display(0, 0); display(0, 1);
delay_ms(50);
}
cntA = cntB = 0;
display(0, 0); display(0, 1);
state = COUNT_A;
}
}
}
關鍵硬體細節
- 按鍵消抖:軟體延遲 10~20ms 或狀態機法,避免一次按下觸發多次計數。
- LED 驅動:單片機 IO 輸出電流有限 (通常 20mA),需加限流電阻或三極管/驅動 IC (ULN2803) 放大。
- 共陽/共陰:共陽輸出低電平點亮,共陰輸出高電平點亮,程式碼取反即可。
- 中斷優化:按鍵接外部中斷腳 (INT0/INT1),ISR 內設旗標,主迴圈處理邏輯,提高回應速度。
專題報告建議章節
- 系統總體設計 (方塊圖、資料流圖)。
- 硬體電路圖 (原理圖 + PCB Layout 截圖)。
- 軟體流程圖 (主程式、中斷、顯示子程式)。
- 關鍵演算法說明 (消抖、閃爍時序、狀態機)。
- 除錯過程與測試數據 (示波器/邏輯分析儀波形)。
- 總結與心得。