使用计时器,我想每隔一秒切换一次 LED。我正在使用 ATMega32,时钟频率为 1MHz。我可以使用 8 位计数器达到 0.1 秒,并且对于每 10 个定时器中断,我闪烁 LED。
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
typedef unsigned char u8_t;
typedef unsigned short u16_t;
void func();
int main(void)
{
DDRC = 0x80;
TCCR0 |= (1 << WGM01); // CTC bit.
TCCR0 |= (1 << CS02) | (1 << CS00); // Prescalar = 1024.
OCR0 = 98; // 98 ticks correspond to roughly 0.1 second with 1024 prescaler
TIMSK |= (1 << OCIE0);
TCNT0 = 0;
sei();
while(1)
{
if (!(TIFR & (1 << OCF0))) {
func();
}
}
}
void func()
{
static u8_t extra_time = 0;
if (extra_time == 10)
{
extra_time = 0;
PORTC ^= 0x80;
}
else extra_time++;
TIFR |= (1 << OCF0);
}
在前面的代码中,我没有为TIMER0_COMP_vect
中断定义 ISR。
从数据表:
当 Timer/Counter0 和 OCR0(输出比较寄存器 0)中的数据发生比较匹配时,OCF0 位置位(1)。OCF0 在执行相应的中断处理向量时由硬件清零。或者,通过将逻辑 1 写入标志来清除 OCF0。当 SREG 中的 I 位、OCIE0(Timer/Counter0 比较匹配中断使能)和 OCF0 置位(1)时,执行 Timer/Counter0 比较匹配中断。
强调我的。
因此,通过强调的句子,我可以检查 OCF0 位是否为零,如果是,我可以“处理”on-compare-match 事件。
但是,LED 闪烁的频率要高得多(每次闪烁之间甚至不到十分之一秒,但我当然无法测量)。
如果我只是将 ISR 设置为打开TIMER0_COMP_vect
并且什么都不检查,这可以正常工作,但我想知道为什么 OCF0 总是(?)逻辑 0,因此“打开”,即使我在每次func()
调用时都将它设置为高。这种方法有什么问题。