给定一个计数器/计时器增加并以给定的位宽简单地换行,对于找到计数器的两个捕获值之间的差(该计数器可能在两点之间换行)的问题,众所周知的解决方案是在计数器上执行无符号减法(如果不知道哪个较大,可以将结果解释为有符号)。
例如,给定一个32位定时器,可以使用如下代码来确定某些代码运行所需的时间:
uint32_t start = GetSomePlatformSpecificTimer();
RunSomeOtherCode();
uint32_t end = GetSomePlatformSpecificTimer();
uint32_t platformTicksTakenByCode = end - start;
或者,检查是否已达到某些时间限制:
uint32_t limit = GetSomePlatformSpecificTimer() + timeLimitInTicks;
while (true)
{
bool finished = DoSomethingSmall();
if (finished)
break;
if ((int32_t)(GetSomePlatformSpecificTimer() - limit) >= 0)
return ERROR_TIMEOUT;
}
如果已知计时器的宽度为32位,则此方法非常有用。通过更改所使用的类型,也可以将其调整为16位或8位定时器。
在计时器大小与类型大小不匹配的情况下,是否有类似的简单方法可以执行相同的操作?例如,一个24位计时器或一个18位计时器。
假定位大小为<= 32,并且由#define COUNTER_WIDTH
某些外部头中的a指定(并且可能会更改)。
最好的解决方案是将两个计数器的值从符号扩展COUNTER_WIDTH
到32位,然后使用上面的代码吗?我可以看到可能适用于FF-> 00过渡,但我认为它将破坏7F-> 80过渡,因此大概必须对此进行某种检查(如果值接近零,则可能会扩展符号)和零扩展(如果值在中点附近)。我认为这也意味着两个值之间的差异不应超过计数器范围的四分之一,否则可能会引起问题。
还是有更好的方法来做到这一点?
您可以乘以使其整个范围变成与算术类型相同的大小,而不是使用符号扩展。换句话说,使用定点算法来填充整数。在您的情况下,使用uint32_t
,则看起来像
uint32_t start = GetSomePlatformSpecificTimer();
RunSomeOtherCode();
uint32_t end = GetSomePlatformSpecificTimer();
start <<= 32-COUNTER_WIDTH;
end <<= 32-COUNTER_WIDTH;
uint32_t platformTicksTakenByCode = end - start;
platformTicksTakenByCode >>= 32-COUNTER_WIDTH;
显然,您希望封装该算法:
const uint32_t start = GetScaledTimer();
RunSomeOtherCode();
const uint32_t end = GetScaledTimer();
const uint32_t platformTicksTakenByCode = RescaleDuration(end - start);
和
uint32_t GetScaledTimer()
{
return GetSomePlatformSpecificTimer() << 32-COUNTER_WIDTH;
}
uint32_t RescaleDuration(uint32_t d)
{
return d >> 32-COUNTER_WIDTH;
}
这样,您就具有了与全角计时器相同的行为,并且在必要时具有使用带符号类型的相同选项。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句