2016-11-02 69 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'是错误的类型,因为溢出未定义。 –

相关问题