一、uwTick
?的作用
1.系統時間基準
uwTick
?是一個全局變量(volatile uint32_t
),記錄系統啟動后的毫秒級時間累計值。默認情況下,它由 SysTick 定時器每 ?1ms?自動遞增一次(通過?HAL_IncTick()
?函數。- 例如,若系統運行了 5 秒,
uwTick
?的值約為?5000。
2.實現延時功能
HAL_Delay()
?函數依賴?uwTick
?實現阻塞延時。其原理是通過記錄起始時刻的?uwTick
?值,并在循環中持續比較當前值與起始值的差值,直到達到設定的延時時間。
3.時間戳生成
- 通過?
HAL_GetTick()
?直接返回?uwTick
,用于標記事件發生的時刻或計算時間間隔(如程序執行耗時)。
二、uwTick
?的使用方法
1.基本延時操作
// 阻塞延時 100ms
HAL_Delay(100);
- 內部邏輯:
HAL_Delay()
?調用?HAL_GetTick()
?獲取當前?uwTick
,循環等待直至時間差達到設定值。?
2.時間間隔計算
uint32_t start = HAL_GetTick();
// 執行某些操作...
uint32_t elapsed_time = HAL_GetTick() - start; // 計算耗時(ms)
- ?注意事項:若時間差超過?
uint32_t
?最大值(約 49.7 天),需額外處理溢出問題。
3.高精度時間測量
結合 SysTick 的當前計數值(SysTick->VAL
)和?uwTick
,可提升時間分辨率至微秒級:
uint32_t start_ms, start_ticks, end_ms, end_ticks;
vGetStartTime(&start_ms, &start_ticks); // 記錄起始時間
// 執行代碼...
vGetIntervalTime(start_ms, start_ticks, &end_ms, &end_ticks); // 計算時間差
float us = end_ms * 1000 + (SysTick->LOAD - end_ticks) * (1e6 / SystemCoreClock); // 轉換為微秒
- SysTick 是遞減計數器,
SysTick->VAL
?提供當前周期內的剩余計數值,與?uwTick
?共同實現高精度計時。
三、配置與注意事項
1.時基源選擇
- 默認使用 SysTick 作為時基源,但可通過 CubeMX 切換為硬件定時器(如 TIM1),以規避中斷優先級沖突或實現更高精度的延時。
- 修改方法:在 CubeMX 的?
SYS
?配置中,選擇其他定時器作為時基源。
2.中斷優先級問題
- 風險:在中斷服務函數(ISR)中調用?
HAL_Delay()
?可能導致死鎖。例如,若高優先級中斷等待 SysTick(低優先級)更新?uwTick
,SysTick 中斷可能無法觸發。 - 修改方法:
避免在中斷中使用阻塞延時,改用非阻塞計時(如標志位 + 輪詢)。
?修改 SysTick 中斷優先級至更高等級(需同步調整其他中斷優先級)。
3.自定義時基頻率?
- 通過調整?
uwTickFreq
?可改變?uwTick
?的更新頻率(如改為 10kHz):
uwTickFreq = 10; // 10kHz(每 0.1ms 更新一次)
HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq));
- 注意:需同步修改?
HAL_GetTick()
?相關邏輯以適配新頻率。
?四、uwTick和Delay函數的核心區別
特性 | uwTick | HAL_Delay() |
---|---|---|
本質 | 全局變量(volatile uint32_t ) | 阻塞延時函數 |
作用 | 記錄系統啟動后的毫秒級累計時間 | 基于?uwTick ?實現固定時長的阻塞延時 |
更新方式 | 由 SysTick 或硬件定時器中斷自動遞增 | 無直接操作,依賴?uwTick ?的更新 |
用途 | 時間戳生成、非阻塞計時、任務調度 | 簡單延時、代碼流程控制 |
中斷安全性 | 可在中斷中使用(需注意優先級沖突) | 禁止在高優先級中斷中使用(可能導致死鎖) |
?五、HAL_Delay()的用法
1.底層原理
- ?
HAL_Delay()
?是阻塞函數,通過循環檢查?uwTick
?的差值實現延時。其核心邏輯如下:
void HAL_Delay(uint32_t Delay) {uint32_t tickstart = HAL_GetTick(); // 獲取起始時間uint32_t wait = Delay;wait += uwTickFreq; // 強制至少延時一個時基周期(默認+1ms)[3,4](@ref)while ((HAL_GetTick() - tickstart) < wait) {} // 阻塞等待[5,7](@ref)
}
- ?誤差特性:默認存在 ?**+1ms** 的固定誤差(如?
HAL_Delay(100)
?實際延時 101ms)。
2.典型應用場景
- ?簡單延時控制:
HAL_Delay(500); // 阻塞延時500ms(實際501ms)
- 外設初始化等待:用于傳感器上電穩定、通信協議間隔等場景。
3.注意事項
- 禁止在高優先級中斷中使用:可能導致 SysTick 中斷無法觸發,
uwTick
?停止更新,函數永不返回。 - 替代方案:在高實時性場景中,改用硬件定時器或非阻塞計時(基于?
uwTick
)。
六、關鍵差異總結
1.角色不同:
uwTick
?是 ?時間基準變量,提供系統時間數據。HAL_Delay()
?是 ?延時工具函數,依賴?uwTick
?實現功能。
2.使用場景:
uwTick
?適用于需要主動獲取時間信息的場景(如性能分析、任務調度)。HAL_Delay()
?適用于簡單的阻塞等待(如初始化等待、調試指示燈閃爍)。
3.實時性影響:
HAL_Delay()
?會阻塞 CPU,影響系統響應;uwTick
?的非阻塞用法更適用于多任務系統。