Search code examples
cembeddedavratmega

blinking a led using timer 1 overflow interrupt in atmega328p


I'm trying to blink a led using ISR for 3seconds, here atmega328p is used. I'm trying to create a 1second delay in isr using TIMER1(16 BIT) and then loop that for 3seconds. LED is connected to PD7, I don't know why it is not blinking, can anyone point out the mistake. I'm using simulIDE, here is the circuit,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++;
}

Solution

  • This code never turn off the LED ... once the bit is set your code never clear it ... try to toggle the bit instead of set it

    #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
      }
    

    update

    1. use volatile access modifier before count variable to tell the compiler that you will Chang it from ISR to make sure that count variable will not delete in optimization
    2. when you set TCCR1B you have to set other bits to zero to operate in normal mode
    3. Recalculate value TCNT1 for 8 MHz which is internal default frequency

    full code

    #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
    }