如何计算时钟为16MHz的ATMega8的C时间

时间:2015-01-22 14:17:25

标签: c time count avr interruption

如何计算中断和设置的时间是一个全局变量? 我的微控制器是Atmega8,F_CPU是16MHz,编程语言是C. 我知道的东西很少,下面这行是时钟的初始化。

TCCR1B |= (1 << CS10);

这一行,全局变量“a”得到的循环值除以“xxx”。但是必须为xxx分配什么值?

a = TCNT1/xxx;

PS1:我想计算推进式LED显示屏中螺旋桨的最后一圈并将此值提供给下一次中断以正确显示图像。

PS2:要做延迟,我使用函数:_delay_ms()。

1 个答案:

答案 0 :(得分:2)

首先使用_delay_ms不是正确计时的好方法。

我建议如下: 使用timer1测量转子的频率。 当您获得位置中断(假设每回合一次)时,将当前计时器值写入变量。在以下每个中断上计算循环计数器的差异(正确考虑溢出)。

现在你有每转的周期数。我现在将以某种方式设置第二个计时器,计数器顶部值(CTC模式)与您测量的循环数相同,除以显示器的角分辨率。因此,在溢出中断中,您可以将新数据锁存到LED。

一个例子:

前提条件/假设:

  • F_CPU(和实际时钟)16MHz
  • 显示分辨率:200角度
  • 转子速度:137Hz
  • 定时器1预分频器= 4(否则每转多次溢出)

使用此值,您应该得到29197个Timer-Ticks的差异,转换为每转116788.3 CPU-Cycles。除以200行,每个部分有583.94个周期。这个数字对于8位计数器来说太大了。使用预分频器2给出291.97 - 仍然太大。所以你必须使用下一个更大的预分频器(希望)4到值145.98。 舍入到146和-1,因为0也被计算在内。 所以我建议使用145作为此计数器的最高值。这种考虑必须以编程方式实施。获取周期值并增加预分频器,只要它不适合你的8位。

整个程序如下所示:

volatile uint16_t oldTimer=0;
volatile uint16_t newTimer=0;
volatile uint8_t  flag=0; // bit 1 = push new data, bit 2 = new revolution measurement

ISR(Postional Interupt){
 oldTimer = newTimer;
 newTimer = TCNT1;
 flag |= 2;
}

ISR(timer2_overflow){
  latchDataToOutput();
  flag |= 1;
}

int main()
{
  while(1){
    if(flag & 2){
      calcNewTimer2Timing();
      flag &= ~2;
    }
    if(flag & 1){
      OutputDataToShiftRegister();
      flag &= ~1;
    }

  }
}