0

来自这个问题,我只是想知道如何计算 Atmega328 定时器在触发中断之前可以给我们的最长时间?我希望它在我的项目中每隔一小时左右触发一次,但由于 C 整数和 OCR1A 寄存器的大小有一些限制,因此要从中获得一个小时似乎还很遥远。

是否可以修改我的最后一个问题代码以延迟几个小时?

4

2 回答 2

2

它应该是,取决于你的微控制器的频率和你要使用的预分频器。

Atmega 328P 为 20 MHz。因此,如果您取 20,000,000/1024 = 19531。这就是 1 秒内的周期数。

您可以在 16 位定时器的数据表中找到:

    volatile uint8_t count = 0;

    void set_up_timer() {
      TCCR1B = (1 << WGM12);       // from the datasheet
      OCR1A = 19531;               // number of ticks in a second
      
      TIMSK1 = (1 << OCIE1A);      // from the data sheet
      TCCR1B |= (1 << CS12) | (1 << CS10);   

您可以设置一个全局变量,并在 ISR 例程中递增它,直到达到所需的值。类似于以下内容:

      ISR(TIMER1_COMP1_VECT) {
        counter++;
        if(counter >= 3600) {
         // do whatever needs to be done
        }
于 2020-10-09T19:41:57.957 回答
1

Jabberwocky 的评论翻译成此代码(基于您发布链接的其他问题)

... includes

/* In milliseconds */
const unsigned int ISR_QUANTUM = 1000; // once in a second

/* How much time should pass (1 hours = 3600 seconds = 3600 * 1000 ms */
const unsigned long LONG_TIME_INTERVAL = 1000 * 3600;

volatile unsigned long time_counter;

void once_an_hour() {
    ... do what needs to be done
}

int main(void) {
    ... setup your timer interrupt (high-precision, "short-range")

    // reset your 'seconds' time counter
    time_counter = 0;

    while (1)
    {
        // busy-wait for time counter passing
        if (time_counter > LONG_TIME_INTERVAL) {
            // reset global timer
            time_counter = 0;
            once_an_hour();
        }

        // do other things
        ...
    }
}

ISR (TIMER1_COMPA_vect)
{
    // action to be done every Xms - just increment the time_counter
    time_counter += ISR_QUANTUM;
}

这样,您只需在“本地”中断处理程序中增加“全局”时间计数器。

于 2020-10-05T19:06:34.907 回答