来自这个问题,我只是想知道如何计算 Atmega328 定时器在触发中断之前可以给我们的最长时间?我希望它在我的项目中每隔一小时左右触发一次,但由于 C 整数和 OCR1A 寄存器的大小有一些限制,因此要从中获得一个小时似乎还很遥远。
是否可以修改我的最后一个问题代码以延迟几个小时?
它应该是,取决于你的微控制器的频率和你要使用的预分频器。
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
}
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;
}
这样,您只需在“本地”中断处理程序中增加“全局”时间计数器。