1

My problem is an interrupt service routine (ISR) that seemingly never executes! Here's some info on my set up: I am flashing an avr attiny85. I have the bare bones of a project set up so far with simply a main.c and two modules: timer and hardwareInit. In the timer module, I have a timer0_init function that I am using to set up timer0 for CTC mode to overflow ever 1 ms. Here is the function:

void timer0_init( void )
{
    cli();
    TCCR0B |= 3;    //clock select is divided by 64.
    TCCR0A |= 2;    //sets mode to CTC
    OCR0A = 0x7C;   //sets TOP to 124 so the timer will overflow every 1 ms.    
    TIMSK |= 2;     //Enable overflow interrupt
    sei();          //enable global interrupts
}

with the timer set up, I added an ISR to increment ticks every time the counter overflows, so I can keep track of how much time has elapsed, etc.

ISR(TIMER0_OVF_vect)
{
    cli();
    //ticks ++;
    PORTB |= ( 1 << PORTB0 );   
    sei();
}

as you can see, I commented out the ticks++ because it wasn't working, and replaced it with PORTB |= ( 1 << PORTB0 ); which simply turns on an LED, so if the interrupt is ever executed, I will know by proof of the LED being on. Unfortunately, I can't get it to turn on and can't see what I'm missing. (to prove that I 1. have the LED set up on the right pin, and 2. am manipulating the correct bit in the correct register, I put just this statement PORTB |= ( 1 << PORTB0 ); in my infinite loop and confirmed the LED came on)

For further explanation, here is my main.c:

/*================================= main.c =================================*/

#define F_CPU   8000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#include "timer.h"
#include "hardwareInit.h"


int main(){

    //Initialize hardware HERE  
    DDRB |= ( 1 << PORTB0 );    //set this pin as an output for an LED

    SetClockPrescale(1);    //internal clock divided by 1 = 8 MHz, from hardwareInit

    timer0_init();          //set up timer0 for 1 ms overflow


    while(1)
    {
        /* if( getTicks() > 0 )
        {
            PORTB |= ( 1 << PORTB0 );
            _delay_ms(1000);
            PORTB &= ~( 1 << PORTB0 );
            _delay_ms(1000);
        } */

    }
    return 0;
}

So, what you see in the infinite loop is what I tried first, but after that didn't work, I tried something simpler, just having an empty loop (commented out previous stuff), and waiting for the interrupt to get triggered which would turn on the LED.

Any help you could give would be really appreciated. I'm quite puzzled why this hasn't been working.

  • 1
    None of this is Arduino. – Ignacio Vazquez-Abrams Nov 20 '16 at 5:16
  • 1
    cli() and sei() are useless in your ISR as interrupts are automatically disabled at ISR start and re-enabled on return. – jfpoilpret Nov 20 '16 at 8:12
  • @jfpoilpret Thank you! I was told that it was a good practice to disable and then re-enable interrupts in an ISR so you don't have interrupts interrupting your ISR. Can you point me to a source that says ISR does that automatically? – chen Nov 22 '16 at 15:00
  • Try commenting OCR0 register's value for overflow interrupt to work .Well it worked for me. – Arvind Bhosle Sep 21 '18 at 7:08
4

You are misunderstanding what an overflow interrupt is. That is called when the timer overflows (ie. it reaches TOP which in the case of an 8-bit timer is 255). Since you are counting to 124 that will never happen, and thus the interrupt will not fire.

You want the "compare A vector" which is called when the "A" register compares to the limit. Example code:

void timer0_init( void )
{
    TCCR0B = bit (CS01) | bit (CS00);    //clock select is divided by 64.
    TCCR0A = bit (WGM01);     //sets mode to CTC
    OCR0A = 0x7C;             //what to count to    
    TIMSK = bit (OCIE0A);     //Enable compare match A interrupt
}

ISR(TIMER0_COMPA_vect)
{
    PINB = bit (PINB0);   // toggle pin 5
}

int main(){

    DDRB |= bit (DDB0);    //set this pin as an output for an LED
    timer0_init();         //set up timer0 for 1 ms overflow
    sei ();                // allow interrupts
    while(true) { }        // forever
    return 0;
}

I changed it to toggle pin 5 (which happens extremely quickly) so it will seem to be on but a bit dim. You can see on an oscilloscope or logic analyzer that it is toggling rapidly.

You don't need to turn interrupts off or on inside an ISR. You are better off using the bit names rather than "magic numbers" in your code, as my example shows.

  • Also note how Nick change TCCR0B |= to TCCR0B =. Since the arduino code uses timer0 for millis, TCCR0B isn't the default value. – Gerben Nov 20 '16 at 14:59
  • Yes, never assume you know what values registers have in them, unless you set them yourself. – Nick Gammon Nov 20 '16 at 20:08
  • Great! I was missing the point of CTC mode. When I set OCR0A to 124, I thought that since the TOP was changed to 124, the timer would overflow when it hit 124. It's now clear to me that overflow is only when the timer reaches the "true" top, in this case 255. Thanks for your help. – chen Nov 22 '16 at 3:38
  • @Gerben and Nick, is it ok to assume the value of the registers when I am flashing the attiny itself, separate from Arduino or anything else that would have already set them? I was going based off of the datasheet for the attiny85 which shows the initial values of each bit in each register: screencast.com/t/ry9FSpyWQt9 – chen Nov 22 '16 at 3:42
  • Probably it is. However I don't really see the point of "or"ing in a bit, when in less (or the same) machine cycles you can just set the desired value. If you assign you definitely get what you want, if you "or" you are just hoping. – Nick Gammon Nov 22 '16 at 5:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.