在 atmega328p 中使用定时器 1 溢出中断闪烁 LED

blinking a led using timer 1 overflow interrupt in atmega328p

我正在尝试使用 ISR 使 LED 闪烁 3 秒,这里使用的是 atmega328p。我正在尝试使用 TIMER1(16 BIT) 在 isr 中创建 1 秒的延迟,然后将其循环 3 秒。 LED接PD7,不知道为什么不闪,谁能指出错误。我用的是simulIDE,这是电路,timer_circuit

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
unsigned int count = 0;
void timer()
{
  TCCR1A = 0x00; // Normal mode of operation
  TCNT1 = 0xC2F8; // decimal value is 49912
  TCCR1B |= ((1 << CS10) | (1 << CS12));
  TCCR1B &= ~(1 << CS11); //1024 prescaler

  sei(); // Global interrupt
}

int main(void)
{
    SET_BIT(DDRD,PD7);
    timer();
    while(1)
    {
        TIMSK1 |= TOIE1;
        if(count>=3)
        {
            SET_BIT(PORTD,PD7);
            count=0;
        }
    }
    ;
    return 0;
}
ISR(TIMER1_OVF_vect)
{
  count++;
}

此代码永远不会关闭 LED ...一旦设置了该位,您的代码就永远不会清除它...尝试切换该位而不是设置它

#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
...
if(count>=3)
  {
     toggle_BIT(PORTD,PD7);
     count=0;
     TCNT1 = 0xC2F8; // reset counter
  }

更新

  1. 在 count 变量之前使用 volatile 访问修饰符来告诉编译器您将从 ISR 更改它以确保 count 变量不会被删除在优化中
  2. 当您设置 TCCR1B 时,您必须将其他位设置为零才能在正常模式下运行
  3. 重新计算 8 MHz 的值 TCNT1,这是内部默认频率

完整代码

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)

volatile unsigned int count = 0;

void timer()
{
    TCCR1A = 0x00; // Normal mode of operation
    TCNT1 = 64754; // over flow after 1 sec calculated at 8 MHZ
    TCCR1B = ((1 << CS10) | (1 << CS12)); //1024 prescaler
    TIMSK1 |= 1<<TOIE1; // Enable timer1 overflow interrupt
    sei(); // Global interrupt
}

int main(void)
{
    SET_BIT(DDRD,PD7);
    timer();
    while(1)
    {
        
        if(count>=3)
        {
            toggle_BIT(PORTD,PD7);
            count=0;
        }
    }
    
    return 0;
}
ISR(TIMER1_OVF_vect)
{
    count++;
    TCNT1 = 64754; // reset to over flow after 1 sec calculated at 8 MHZ
}