jra*_*rez 12 c embedded integer-overflow
我需要处理一个计数器,它为我的应用程序提供了滴答声.计数器是32位,所以我需要知道的是如何在它包装时处理它.例如:
我有一个函数返回一个(timestamp + shifttime),我有另一个函数将返回1或0取决于时间是否已经过去,但我的计数器可能会包装如何处理这个? .
谢谢
非常感谢所有回复的人.我将在此编辑中提供更多详细信息.
我使用的是STM32 Cortex-M3.我想使用RTC计数器将其用作我的应用程序的滴答,以安排需要以特定间隔发生的任务.RTC可以产生溢出中断,因此检测中断不是问题.我遇到的主要问题(或者至少我认为是一个问题)是某些任务获得(时间戳+班次),即.
int main( void )
{
FlashLedTimeStamp = ReturnCounter( 20 ); // currentcounter value + a shift of 20
StatusLedTimeStamp = ReturnCounter( 3 ); // currentcounter value + a shift of 3
//then later on ....
while(1)
{
/* other tasks could go here */
if( HasTimeElapsed( FlashLedTimeStamp );
{
/* do something and get another timestamp value */
FlashLedTimeStamp = ReturnCounter( 20 ); // currentcounter value + a shift of 20
}
if( HasTimeElapsed( StatusLedTimeStamp );
{
/* do something and get another timestamp value */
FlashLedTimeStamp = StatusLedTimeStamp( 3 ); // currentcounter value + a shift of 3
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们假设我的RTC计数器只有8位长,以便简化数学运算.
如果我的当前计数器是250,当我得到我的时间戳,这意味着FlashLedTimeStamp = 14和StatusLedTimeStamp = 253我将如何检查FlashLedTimeStamp是否已经过期?
请记住,我没有必要一直检查当前计数器是什么以及某个时间戳是否已过期.我希望这能说清楚我所面临的问题是多少先进的.
Cli*_*ord 21
只要开始和结束计数之间的差异小于(2 ^ 32)/ 2,并且假设执行2的补码32位算术(几乎普遍为真),即使计数值跨越包络点,也无关紧要.例如:
Start count: 0xfffffff
End Count: 0x00000002 (incremented through 0,1,2 - i.e. three counts)
End - Start == 0x00000002 - 0xfffffff == 0x00000003
Run Code Online (Sandbox Code Playgroud)
因此,只要计数器是内置整数类型的位宽,并且使用该类型,就可以实现正确的答案.如果计数器寄存器可能不是内置整数类型的宽度,则可以通过屏蔽高阶"溢出"位来实现相同的效果.
如果由于其他原因需要更大的计数,或者如果连续时间戳之间的差异太大,那么您可以简单地使用另一个在低阶计数器换行时递增的整数.该整数将形成较大整数的高位,因此第二个整数的LSB是该较大整数的第33位.
bta*_*bta 13
如果您读取两个时间戳读数并且您的第一次读数大于第二次读数,那么您的计数器已经包装好了.这是检测包装计数器的基本方法.
然而,这不会检测计数器是否已经多次包裹,或者计数器已经包裹并且恰好大于第一次读数的情况.既然你说这是一个嵌入式系统,你的描述使你的"计数器"听起来像一个时钟,看看你是否可以设置一个中断,以便在时钟到零时触发(这样你每次时钟复位时都会得到一个中断).当此中断触发时,增加一个单独的计数器.这应该有效地为您的时钟增加额外的精度,并允许您的计数器包装而不会导致问题.
将无符号减法的结果转换为有符号并与零进行比较。当您经常检查它时应该处理溢出(并且您的超时小于计时器范围的一半)。
uint32_t timer( void); // Returns the current time value
uint32_t timeout;
timeout = timer() + offset;
// wait until timer() reaches or exceeds timeout value
while ((int32_t)(timeout - timer()) > 0);
Run Code Online (Sandbox Code Playgroud)
如果您使用无符号变量来存储您的计数器和计时器到期时间,那么您可以简单地使用这个测试:
if (current_time - expiry_time < 0x80000000UL)
/* timer has expired */
Run Code Online (Sandbox Code Playgroud)
这假设您至少每 0x80000000 个滴答测试一次到期,并且您最长的计时器设置为在未来不到 0x80000000 个滴答时到期。