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

C語言延時函數原理:空指令循環、硬件定時器、操作系統調度

     編輯:C 語言問答

三種層級的延時實現

1. 軟件空循環延時 (裸機/單片機最常見)

// 粗略延時,依賴編譯器不優化掉空循環
void delay_naive(unsigned int count) {
    while (count--) {
        __asm__ volatile("nop");  // 防止編譯器優化刪除
    }
}

// 校準版:根據時鐘頻率計算循環次數
// 假設 1 條指令 1 周期,主頻 72MHz,目標 1ms
// 需 72000 周期,每循環約 3-4 指令 → count ≈ 18000
void delay_ms(unsigned int ms) {
    const unsigned int loops_per_ms = 18000;  // 需實測/示波器校準
    while (ms--) {
        for (volatile unsigned int i = 0; i < loops_per_ms; i++);
    }
}
  • 優點:無硬件依賴、極簡代碼、中斷不影響精度 (若不讓出 CPU)。
  • 缺點:佔用 CPU 100%、精度受編譯器優化/指令流水線/中斷影響、功耗高。

2. 硬件定時器延時 (單片機/嵌入式標準做法)

// STM32 HAL 庫示例
void delay_us(uint32_t us) {
    __HAL_TIM_SET_COUNTER(&htim6, 0);
    HAL_TIM_Base_Start(&htim6);
    while (__HAL_TIM_GET_COUNTER(&htim6) < us);
    HAL_TIM_Base_Stop(&htim6);
}

void delay_ms(uint32_t ms) {
    while (ms--) delay_us(1000);
}
  • 優點:精度高 (µs 級)、CPU 空閒可進入低功耗/處理其他任務 (配合中斷)、不受編譯優化影響。
  • 缺點:需配置時鐘源、預分頻、自動重裝載值、啟用定時器外設。

3. 操作系統級延時 (Linux/Windows/RTOS)

Sleep 源碼級原理 (以 Linux glibc 為例)

// 簡化版 nanosleep 實現邏輯
int nanosleep(const struct timespec *req, struct timespec *rem) {
    // 1. 參數校驗
    // 2. 系統調用 SYS_nanosleep (x86_64: syscall 35)
    // 3. 內核:
    //    a. 將當前任務狀態置 TASK_INTERRUPTIBLE
    //    b. 將喚醒時間加入定時器輪 (timer wheel) 或紅黑樹 (hrtimer)
    //    c. 調用 schedule() 切換到其他任務
    //    d. 定時器中斷到期 → 將任務重新加入運行隊列
    //    e. 任務再次被調度運行,返回用戶態
    // 4. 若被信號喚醒,計算剩餘時間存入 rem,返回 EINTR
}

選型建議

  • 裸機單片機:硬件定時器 + 中斷/輪詢,禁用空循環 (除非極簡項目)。
  • RTOS 任務:vTaskDelay / 延時信號量,釋放 CPU 給其他任務。
  • Linux 用戶態:nanosleep / clock_nanosleep,精度較高、可被信號中斷。
  • 高精度忙等 (用戶態):busy-wait + RDTSC/clock_gettime,僅用於極短延時 (<10µs) 且獨佔 CPU 核心場景。

理解「忙等燒 CPU」vs「睡眠讓調度」的本質區別,是寫出高性能、低功耗、實時確定性代碼的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
環境API精度特點
Linux (POSIX)nanosleep(), clock_nanosleep()納秒 (實際受調度器影響,通常 ~µs)可中斷、支持絕對/相對時間、高精度定時器
Linux 內核mdelay(), udelay(), usleep_range()忙等/可調度內核態不可睡眠用忙等,可睡眠用睡眠
WindowsSleep() (ms), SleepEx(), WaitForSingleObject()毫秒 (系統時鐘間隔 ~15.6ms 可調)線程進入等待狀態、釋放 CPU
FreeRTOSvTaskDelay() (tick), vTaskDelayUntil()Tick 精度 (通常 1ms)任務切換、支持周期性喚醒
標準 C (C11)thrd_sleep()實現定義可移植但精度不可控