AVR中断配置

时间:2016-12-27 19:49:54

标签: c timer embedded avr atmel

问题在于时序行为完全错误(因素30)。

我有一台运行8 Mhz的ATmega 644PA(没有设置CKDIV8保险丝)。
我想要每1 ms一次中断。我在比较模式下使用Timer1(16位定时器)。
预分频器由我需要的时序范围选择。
这里1毫秒到2秒。 (通过16位定时器寄存器限制。)

计算

CPU:8.000.000 Hz
预分频器:256

8.000.000 Hz / 256 = 31250周/秒(Hz)

1000 ms = 31250周期
1 ms = 30.25周期(31.25 - 1,定时器寄存器开始0)

从这里我可以计算出来,例如:
100 ms = 3025周期
2s = 60500周期

代码

定时器初始化

    cli();                  // disable global interrupts
    TCCR1A = (1 << WGM01);  // CTC ON
    TCCR1B = 0x04;          // Prescaler 256
    OCR1A  = 30;            // set compare reg.
    TIMSK1 = (1 << OCIE1A); // set interrupt mask
    TCNT1  = 0x00;          // set counter reg. to zero
    sei();                  // enable global interrupts

ISR:

ISR(TIMER1_COMPA_vect)
{
  // start own code
  ...
  // end own code
  TCNT1 = 0x00; // reset counter reg. to zero after match (same which should CTC do)
}

现在我有一个易变量,它将在ISR函数中递增。
我轮询变量并等待很长时间,直到它达到60500,等于2s。
在它之后,我只是设置了一个led。

我通过电话测量它,它需要1分钟,直到LED继续。
因子30 =&gt;需要很长时间。 60秒除以2为30 我也尝试使用外部程序来计算它,它得出了相同的结果。 (0x1E = 30)
Screenshot http://image.prntscr.com/image/14bd89cb111d4653bd27a9e8a8719b93.png

有人知道我的错误在哪里?

1 个答案:

答案 0 :(得分:1)

2秒是60500个周期。但是你的ISR每1毫秒递增一次volatile变量。当然,变量需要60.5秒才能达到60500。

作为旁注,最好更改比较值,而不是重置TCNT,以避免时序漂移。也就是说,让计数器自由运行,并使用OCR1A += 31;命中下一个中断。像你一样重置TCNT将忽略ISR内的时间。