目前,我正在开发一个嵌入式项目,其中大多数子系统都基于时序。
我已经搜索了许多解决方案,以避免计时器翻滚的问题,但还有一件事让我感到困惑。
目前,我正在使用这种无符号长号的两个补码。
ulong t1 = tick of last event;
ulong t2 = current tick;
if ( t2 - t1 >= limit ){
do something
}
其他人已经建议,有必要将t2-t1的结果转换为已签名的实体,然后才能生效,但我无法理解为什么。还有其他任何见解或建议吗?
答案 0 :(得分:2)
有时我会这样做:
ulong t1 = tick of last event;
ulong t2 = current tick;
if ( t1 > t2 ){
if ((ULONG_MAX-t1+t2+1)>=limit){
do something
}
} else {
if ( t2 - t1 >= limit ){
do something
}
答案 1 :(得分:0)
如果保证t2
在概念上始终大于t1
,则转换为已签名的实体将是错误的。标准保证无符号整数的算术是正确的模UTYPE_MAX + 1
,因此当计算为t2 - t1
s时,差ULONG_MAX + 1
将是正确的模unsigned long
。当转换为已签名的实体时,如果该值在目标类型中不可表示,则行为是实现定义的。通常会将大的正值转换为负值。
测试
if ( t2 - t1 >= limit ){
如果当前滴答计数与之前没有包装计时器之间的差异变得大于ULONG_MAX
,将会中断,否则它会起作用。
但如果t2
可能早于t1
,则真正的差异t2 - t1
将为负数,但作为unsigned long
,它可能是一个潜在的大正数。然后,在使用无符号类型的情况下,转换为带符号的类型可以正常工作。
答案 2 :(得分:0)
您不必将其转换为签名。如果“做某事”是警报处理代码,限制是时间间隔。
定期间隔的最佳做法是:
ulong next_alarm_ticks = 0;
void poll_alarm()
{
if (get_ticks() - next_alarm_ticks < ULONG_MAX/2) {
// current time is "greater" than next_alarm_ticks
handle_alarm();
next_alarm_ticks += alarm_interval;
}
}