三種層級的延時實現
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)
| 環境 | API | 精度 | 特點 |
| Linux (POSIX) | nanosleep(), clock_nanosleep() | 納秒 (實際受調度器影響,通常 ~µs) | 可中斷、支持絕對/相對時間、高精度定時器 |
| Linux 內核 | mdelay(), udelay(), usleep_range() | 忙等/可調度 | 內核態不可睡眠用忙等,可睡眠用睡眠 |
| Windows | Sleep() (ms), SleepEx(), WaitForSingleObject() | 毫秒 (系統時鐘間隔 ~15.6ms 可調) | 線程進入等待狀態、釋放 CPU |
| FreeRTOS | vTaskDelay() (tick), vTaskDelayUntil() | Tick 精度 (通常 1ms) | 任務切換、支持周期性喚醒 |
| 標準 C (C11) | thrd_sleep() | 實現定義 | 可移植但精度不可控 |
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「睡眠讓調度」的本質區別,是寫出高性能、低功耗、實時確定性代碼的關鍵。
- 上一篇文章: C語言數組指針函數錯誤修正:宏定義衝突、局部數組返回、邊界越界
- 下一篇文章: 零基礎自學C語言與計算機技術:書籍、網站、學習路徑全攻略
Copyright ©
程式碼之家 All Rights Reserved