在8位系统上读出一个16位定时器,没有用于高/低字节的锁存器

时间:2013-07-09 07:16:42

标签: timer microcontroller c99

我有一个定期使用的计时器来收集性能值。 现在,我已经看到,有时候,我得到的值低于之前采样的值。

我发现将这种行为追溯到我做的事实:
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()函数。)
这需要边缘条件,即定时器的周转时间大于上面代码的执行时间!

2 个答案:

答案 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在阅读upper1upper2之间溢出,则在阅读upper2lower2之间不会再次溢出。

由于在分配块周围禁用了中断,因此它应该总是足够快,即使对于8位计数器也是如此。