基於 8051 單片機(reg52.h),利用定時器 0 中斷實現 0.1 秒計時,外部中斷 0/1 對應「開始/暫停」與「重置」按鍵,數碼管動態掃描顯示。
P2.7 (WEI):位選鎖存器(選擇哪個數碼管)P2.6 (DUAN):段選鎖存器(顯示什麼數字)P3.4 (L1):指示燈P3.2 (INT0):按鍵 8 — 開始/暫停P3.3 (INT1):按鍵 C — 重置unsigned char code DuanMa[11] = {
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40
}; // 0-9, 10=空白
unsigned char code WeiMa[8] = {
0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F
}; // 8 位位選碼
int sec = 0; // 秒計數 (0-99)
int num = 0; // 總秒數 (0-14, 15秒歸零)
int i = 0; // 0.1秒計數 (0-100)
int flag = 1; // 運行標志:1=運行, 0=暫停
void Screen(int pos, int val) {
P0 = 0; DUAN = 1; DUAN = 0; // 段選清零
P0 = WeiMa[pos]; WEI = 1; WEI = 0; // 位選
P0 = DuanMa[val]; DUAN = 1; DUAN = 0; // 段選數值
}
void Timer0_ISR() interrupt 1 using 1 {
TH0 = (65536 - 10000) / 256; // 1ms @ 12MHz (10000 個機器周期)
TL0 = (65536 - 10000) % 256;
if (flag) {
i++; // 0.1ms 計數
sec++; // 顯示用 0.01 秒計數 (0-99)
if (sec == 100) sec = 0;
if (i == 101) { // 101 * 1ms ≈ 1秒 (實際 10.1ms? 需核對晶振)
i = 0;
num++;
if (num == 15) num = 0; // 上限 15 秒演示
}
}
}
void EXT0_ISR() interrupt 0 {
flag = !flag; // 切換運行狀態
}
void EXT1_ISR() interrupt 2 {
if (!flag) { // 僅暫停狀態可重置
sec = 0;
num = 0;
// 可選:直接刷新顯示
}
}
void main() {
// 中斷初始化
EA = 1; // 總中斷
ET0 = 1; // 定時器 0
EX0 = 1; IT0 = 1; // INT0 下降沿
EX1 = 1; IT1 = 1; // INT1 下降沿
// 定時器 0 模式 1 (16位)
TMOD |= 0x01;
TH0 = (65536 - 10000) / 256;
TL0 = (65536 - 10000) % 256;
TR0 = 1; // 啟動定時器
WEI = 0; DUAN = 0;
L1 = 0;
while (1) {
// 動態掃描顯示:位 3-4 顯示 num,位 6-7 顯示 sec
if (num >= 10) Screen(3, num / 10);
Screen(4, num % 10);
Screen(5, 10); // 空白分隔
Screen(6, sec / 10);
Screen(7, sec % 10);
// 簡單延時避免閃爍
for (int d = 0; d < 1000; d++);
}
}
using 1 指定寄存器組 1,加速上下文切換flag 控制計時邏輯啟停,num 為業務計數器