1. 程式人生 > >void HAL_Delay(__IO uint32_t Delay) 函式溢位的問題

void HAL_Delay(__IO uint32_t Delay) 函式溢位的問題

計數器的更新

計數器uwTick是在每次Systick中斷中加一更新,此處配置Systick中斷為每1ms中斷一次。uwTickuint32_t型別,那麼uwTick的最長計時為0xFFFFFFFF毫秒(約為49.7天),也就是說 uwTick 會在系統持續執行49天后溢位清零。

函式的實現

void HAL_Delay(__IO uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();
  while((HAL_GetTick() - tickstart) < Delay)
  {
  }
}

函式中計時的實現是通過迴圈讀取uwTick 變數,比較差值來實現延遲,那麼當計數器溢位時,此函式是否繼續有效呢?

無符號整數的特性

我們知道:1 - (-1) = 2
將其轉換為32位補碼形式為:0x00000001 - 0xFFFFFFFF = 0x00000002
HAL_GetTick()0xFFFFFFFF時,正好將tickstart賦值。而當計數器溢位重新開始比較的時候,可以發現,上面的比較方式任然成立
此處需要注意HAL_GetTick()返回的無符號型別要與當前CPU的位數一致。
uint16_t a = 0xffff,在32位系統中參與運算,賦值到32位的暫存器變數中變為0x0000FFFF,運算的結果顯然不正確。

linux 的解決方法

在linux中,jiffies溢位是通過time_after和time_before巨集來解決

#define time_after(a,b)        \
    (typecheck(unsigned long, a) && \
     typecheck(unsigned long, b) && \
     ((long)(b) - (long)(a) < 0))
#define time_before(a,b)    time_after(b,a)

#define time_after_eq(a,b)    \
    (typecheck(unsigned long, a) && \
     typecheck(unsigned long
, b) && \ ((long)(a) - (long)(b) >= 0)) #define time_before_eq(a,b) time_after_eq(b,a) #define time_in_range(a,b,c) \ (time_after_eq(a,b) && \ time_before_eq(a,c)) /* Same as above, but does so with platform independent 64bit types. * These must be used when utilizing jiffies_64 (i.e. return value of * get_jiffies_64() */ #define time_after64(a,b) \ (typecheck(__u64, a) && \ typecheck(__u64, b) && \ ((__s64)(b) - (__s64)(a) < 0)) #define time_before64(a,b) time_after64(b,a) #define time_after_eq64(a,b) \ (typecheck(__u64, a) && \ typecheck(__u64, b) && \ ((__s64)(a) - (__s64)(b) >= 0)) #define time_before_eq64(a,b) time_after_eq64(b,a)

其中需要保證ab均為無符號整數