2016-11-02 70 views
0

我正在關注Keil的CMSIS-RTOS Tutorial。它提供了以下方法把亞毫秒延遲:檢查osKernalSysTick()是否需要環繞?

條:亞毫秒延遲

int32_t tick,delayPeriod; 
tick = osKernelSysTick(); // get start value of the Kernel system tick 
// Then we can scale a period in microseconds to a SysTick count value 
delayPeriod = osKernelTickMicroSec(100)); 
// This then allows us to create a delay for the the required period. 
do { // Delay for 100 microseconds 
} while ((osKernelSysTick() - tick) < delayPeriod); 

的osKernelSysTick()返回一個滾動的32位計數器的值;這個實現不會迎合該值的包裝。

如果發生包絡,則無法達到預期的延遲。這是官方Keil文檔中的錯誤還是我錯過了一些東西?

+1

_「這個實現不能滿足那個值的包裝」_ - 你確定嗎?嘗試通過數學計算環繞情況,同時記住二進制補碼算術。 – Notlikethat

+0

@Muhammad - 讓事情變得複雜,您還必須擔心優化器進行優化和/或刪除上面顯示的未定義行爲。他們可以通過使用'uint32_t'來避免很多額外的麻煩。另請參閱Ian Lance Taylor在[Signed Overflow]上的博客(http://www.airs.com/blog/archives/120)。並記住*有符號整數溢出*是未定義的行爲,而*無符號整數包裝*是明確定義的行爲。 – jww

+0

函數原型是'uint32_t osKernelSysTick(void)'它返回一個無符號的值。變量'ticks'類型應該被改變。 – Gerhard

回答

3

由於算術的完成方式,所顯示的實現不適合環繞。

do { // Delay for 100 microseconds 
} while ((osKernelSysTick() - tick) < delayPeriod); 

當定時器換行時,這會導致算術溢出。

如果您使用unsigned變量並計算之前的縮小時間,並將其與所需的時間段進行比較,您將避免這種情況。無符號變量由C標準保證包裝。

uint32_t tick, delayPeriod, elapsed;   // unsigned 
tick = osKernelSysTick(); 
delayPeriod = osKernelTickMicroSec(100)); 

do { 
    elapsed = osKernelSysTick() - tick;   // separate arithmetic wraps cleanly 
} while (elapsed < delayPeriod); 

注意函數無論如何定義爲uint32_t osKernelSysTick,所以最初的例子是使用符號類型不正確。

+0

肯定不需要明確的中間變量,因爲一切都可以用int表示,或者它全部通過通常的算術轉換自動提升爲無符號。 – Notlikethat

+0

@Notlikethat分離防止算術溢出和比較之間的混淆。正如我已經解釋的那樣,'int'是錯誤的類型,因爲溢出未定義。 –

相關問題