1


I try to use the Timer0 of an Arduino Leonardo (ATmega32u) to trigger an interrupt at regular intervals, using plain avr-gcc (not the arduino library). I try to blink the built-in LED as test, but it does not light up.

If I place a PINC=0x80; in the main function, the LED turns up, but not if I do it from the interrupt. What am I doing wrong?

EDIT : The LED turns on with TCCR0B = (1 << CS00);, (no prescaler) or TCCR0B = (1 << CS01) (prescaler /8), but it does not with TCCR0B = (1 << CS00) | (1 << CS02); (prescaler /1024, what I want). At 16MHz CPU frequency the resulting frequency should be more than 15kHz, so I should see it instantly.

Here is my code:

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

ISR(TIMER0_OVF_vect)
{
    PINC = 0x80;
}

int main()
{
    DDRC = 0b10000000;

    //Start Timer 0 @ 15625 Hz
    TCCR0A = 0;
    TCCR0B = (0b101 << CS00);
    TIMSK0 = (1 << TOIE0);
    sei();

    while(true); // Avoid return from main
}
  • what research have you done? – jsotola Apr 24 '18 at 19:00
  • @jsotola I read the corresponding chapters of the processor datasheet and googled for a while, but I only found unrelated issues (e.g. using CTC mode or returning from main). – Simon Tagne Apr 24 '18 at 19:00
  • i misread .... deleting my comments .... you can delete yours – jsotola Apr 24 '18 at 19:07
  • then you have to assume that the ISR is never called .....maybe this may help ....... instructables.com/id/Arduino-Timer-Interrupts – jsotola Apr 24 '18 at 19:10
  • Sidenote: 0b101 << CS00 looks like bad code. Personally; I’d use (1 << CS00) | (1 << CS02) – Gerben Apr 25 '18 at 15:11
0

I just found the answer here : https://www.avrfreaks.net/forum/atmega32u4-arduino-leonardo-strange-timer-behavior

It seems that the USB connection generates higher-priority interrupts. I still don't know why the interrupts do work at higher frequency.

Solutions include powering the board from a USB charger or other power source rather than through the computer USB or adding the following code before the interrupt enable :

// Clear usb interrupt flags
USBINT = 0;
UDINT  = 0;
for (uint8_t i = 0; i < 6; i++)
{ // For each USB endpoint
    UENUM = i; // select the _i-th endpoint
    UEINTX = UEIENX = 0; // Clear interrupt flags for that endpoint
}

Thanks to those who helped me !

  • I think the interrupt handler is missing when the bootloader exits, so avr-gcc defaults to reset the board, which might result in higher frequency to switch on the led while at lower frequency the board is reset before the first interrupt. – Simon Tagne Apr 24 '18 at 20:13

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.