我有一个定期使用的计时器来收集性能值。 现在,我已经看到,有时候,我得到的值低于之前采样的值。
我发现将这种行为追溯到我做的事实:
1)读取低位字节
2)读取高位字节
value = upper<< 8&lower
但有时会发生什么:
1)读取低位字节
2)发生低位字节溢出,低位= 0,高位++
3)读取高位字节(现在太高了!)
value =(上<<<<<<<<<<<<<<<<<<<"
如果我切换订单:
1)读取高位字节
2)发生低位字节溢出,低位= 0,高位++
3)读取低位字节(现在太低了!)
值=(上限<< 8)+下限 - [值小于255]
所以,在这两种情况下,我都偏离了我的真实价值。
<小时/> 有没有比下面提供的更好的解决方案?
我现在做的是:
/* Sample as long as it takes to not hit an overflow
between sampling the lower and the upper byte */
do {
upper = CounterH;
lower = CounterL;
} while (upper != CounterH);
但是我害怕,因为这有可能陷入僵局! (如果计时器计数足够快)
我也在考虑这个:
__DI();
upper = CounterH;
lower = CounterL;
value1 = upper<<8 + lower;
upper = CounterH;
lower = CounterL;
value2 = upper<<8 + lower;
value = max(value1, value2);
__EI();
(首先读取低位字节然后需要min()函数。)
这需要边缘条件,即定时器的周转时间大于上面代码的执行时间!
答案 0 :(得分:2)
首先,我会检查计数器值是否在读取高字节或低字节时锁存。很多计时器都有。
你的第二种方法(两次读取计数器)很有希望,但如果可能的话,删除计时器的第一次和第二次读取之间的任何计算,然后进行所有计算。此外,您还需要检查高字节环绕(从255到0)是否也是一个问题。
如果您在问题中说明了您正在使用的8位控制器和计时器,那将会很有帮助,因为人们可以通过查看数据表和手册来提供更具体的建议
答案 1 :(得分:2)
你可以展开你的第一个方法进行两次迭代,所以你得到了
__DI();
upper1 = CounterH;
lower1 = CounterL;
upper2 = CounterH;
lower2 = CounterL;
__EI();
if ( upper1 == upper2 )
{
// use lower1, upper1
}
else
{
// use lower2, upper2
}
这里假设如果CounterL
在阅读upper1
和upper2
之间溢出,则在阅读upper2
和lower2
之间不会再次溢出。
由于在分配块周围禁用了中断,因此它应该总是足够快,即使对于8位计数器也是如此。