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

C語言實現可設置時間的電子鐘程序設計思路

     編輯:C 語言問答

電子鐘 C 語言程序設計:從需求到代碼架構

需求:無鍵盤啟動自動走時;鍵盤輸入 A/E 進入設置模式,分別設置時/分/秒,含合法性校驗(時<24,分/秒<60);設置完成按 E 啟動走時。

系統架構設計

  1. 時間數據模型:struct Time { uint8_t h, m, s; }。
  2. 狀態機:
    • RUNNING:正常走時,每秒更新顯示。
    • SET_HOUR、SET_MIN、SET_SEC:設置狀態,接收數字鍵輸入,顯示閃爍對應位。
  3. 輸入處理:非阻塞鍵盤掃描(kbhit() + getch())或中斷驅動。
  4. 顯示驅動:控制台 printf("\r%02d:%02d:%02d", h, m, s) 或七段數碼管/LED 矩陣驅動。
  5. 定時基準:Windows Sleep(1000)、Linux sleep(1)、嵌入式硬體定時器中斷(1Hz)。

核心邏輯偽代碼

Time current = {0,0,0};
State state = RUNNING;

while (1) {
    if (kbhit()) {
        char key = getch();
        handle_key(key, &state, ¤t);
    }

    if (state == RUNNING) {
        update_display(current);
        sleep_ms(1000);
        tick_time(¤t);  // 秒進位邏輯
    } else {
        update_display_blink(current, state);  // 設置位閃爍
        sleep_ms(200);
    }
}

void handle_key(char key, State *st, Time *t) {
    switch(*st) {
        case RUNNING:
            if (key == 'A') *st = SET_HOUR;
            break;
        case SET_HOUR:
            if (isdigit(key)) input_digit(&t->h, key);
            else if (key == 'E') { if (t->h < 24) *st = SET_MIN; else beep_error(); }
            break;
        case SET_MIN:
            if (isdigit(key)) input_digit(&t->m, key);
            else if (key == 'E') { if (t->m < 60) *st = SET_SEC; else beep_error(); }
            break;
        case SET_SEC:
            if (isdigit(key)) input_digit(&t->s, key);
            else if (key == 'E') { if (t->s < 60) *st = RUNNING; else beep_error(); }
            break;
    }
}

關鍵難點與解決方案

難點解決方案
控制台無閃爍顯示用 \r 回車符覆蓋同一行,fflush(stdout) 強制刷新
非阻塞鍵盤輸入Windows: _kbhit()/_getch() (conio.h);Linux: select() 監聽 stdin 或 ncurses 庫
精確 1 秒定時嵌入式用硬體定時器;PC 端用高精度計時器 QueryPerformanceCounter / clock_gettime 校準 sleep
數字鍵多位輸入維護輸入緩衝區,如連按 '1','2' 組成 12,超時或滿兩位自動確認

嵌入式移植提示

  • 裸機/RTOS:將 tick_time 放入 1Hz 定時器中斷服務程序 (ISR);主循環處理按鍵掃描與顯示刷新。
  • 按鍵消抖:硬體 RC 或軟體 20ms 延時確認。
  • 斷電保存:掉電前將時間寫入 RTC 或 EEPROM,上電讀取初始化。

完整可運行控制台版(Windows)

#include <stdio.h>
#include <windows.h>  // Sleep, system
#include <conio.h>    // _kbhit, _getch

typedef struct { uint8_t h, m, s; } Time;

void tick(Time *t) {
    if (++t->s == 60) { t->s = 0; if (++t->m == 60) { t->m = 0; if (++t->h == 24) t->h = 0; } }
}

int main() {
    Time t = {0,0,0};
    enum { RUN, SET_H, SET_M, SET_S } state = RUN;
    int blink = 0; char buf[4] = {0}; int buf_len = 0;

    while (1) {
        if (_kbhit()) {
            char k = _getch();
            if (state == RUN && k == 'A') { state = SET_H; buf_len = 0; }
            else if (state != RUN) {
                if (k >= '0' && k <= '9' && buf_len < 2) { buf[buf_len++] = k; }
                else if (k == 'E') {
                    int val = atoi(buf);
                    if (state == SET_H && val < 24) { t.h = val; state = SET_M; buf_len = 0; }
                    else if (state == SET_M && val < 60) { t.m = val; state = SET_S; buf_len = 0; }
                    else if (state == SET_S && val < 60) { t.s = val; state = RUN; }
                    else { printf("\a"); }  // 蜂鳴報錯
                }
            }
        }

        if (state == RUN) {
            printf("\r%02d:%02d:%02d", t.h, t.m, t.s);
            fflush(stdout);
            Sleep(1000);
            tick(&t);
        } else {
            const char *labels[] = {"", "H", "M", "S"};
            blink = !blink;
            char h = (state==SET_H && !blink) ? ' ' : '0'+t.h/10;
            // 簡化顯示邏輯...
            printf("\r設置%s: %s", labels[state], buf);
            fflush(stdout);
            Sleep(200);
        }
    }
}

總結

電子鐘看似簡單,實則包含狀態機、定時器、輸入處理、顯示驅動、數據校驗等嵌入式核心要素。建議先在 PC 控制台跑通邏輯,再移植至單片機(STM32/51/ESP32),逐步替換 HAL 層。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved