首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

單片機 C 語言實現秒表:定時器中斷 + 外部中斷按鍵控制

     編輯:關於C語言

單片機 C 語言實現秒表:定時器中斷 + 外部中斷按鍵控制

基於 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; // 段選數值
}

定時器 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 秒演示
        }
    }
}

外部中斷 0:開始/暫停切換

void EXT0_ISR() interrupt 0 {
    flag = !flag;  // 切換運行狀態
}

外部中斷 1:重置歸零

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++);
    }
}

五、關鍵技術點總結

  1. 動態掃描:高頻切換位選,利用視覺暫留效應實現多位顯示
  2. 中斷嵌套:using 1 指定寄存器組 1,加速上下文切換
  3. 按鍵消抖:硬件電容或軟件延時(代碼中省略,實際需添加)
  4. 定時器計算:12MHz 晶振,機器周期 1μs,10000 周期 = 10ms,實際 0.01 秒/中斷
  5. 狀態機:flag 控制計時邏輯啟停,num 為業務計數器

六、擴展建議

  • 添加軟件消抖:中斷中延時 10ms 再確認電平
  • 使用定時器 1 做按鍵掃描,釋放外部中斷資源
  • 實現分/秒/毫秒完整秒表,增加暫停後繼續功能
  • 移植到 STM32:HAL 庫 + SysTick + EXTI,代碼結構相似
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved