Прерывание переполнения Timer0 не работает


Я пытаюсь использовать Timer0 Arduino Leonardo (ATmega32u) для запуска прерывания через равные промежутки времени, используя простой avr-gcc (не библиотеку arduino). Пытаюсь для проверки помигать встроенным светодиодом, но он не загорается.

Если я помещаю PINC=0x80; в основную функцию, светодиод загорается, но не в том случае, если я делаю это из прерывания. Что я делаю не так?

EDIT: светодиод загорается при TCCR0B = (1 << CS00);, (без прескалера) или TCCR0B = (1 << CS01) (предделитель /8), но не с TCCR0B = (1 << CS00) | (1 << CS02); (предделитель /1024, то, что я хочу). При частоте процессора 16 МГц результирующая частота должна быть больше 15 кГц, поэтому я должен увидеть это сразу.

Вот мой код:

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

ISR(TIMER0_OVF_vect)
{
    PINC = 0x80;
}

int main()
{
    DDRC = 0b10000000;

    //Запуск таймера 0 при 15625 Гц
    TCCR0A = 0;
    TCCR0B = (0b101 << CS00);
    TIMSK0 = (1 << TOIE0);
    sei();

    while(true); // Избегайте возврата из main
}

, 👍0

Обсуждение

какое исследование вы провели?, @jsotola

@jsotola Я прочитал соответствующие главы таблицы данных процессора и некоторое время гуглил, но нашел только несвязанные проблемы (например, использование режима CTC или возврат из основного)., @Simon Tagne

я невнимательно прочитал....удалив мои комментарии....можете удалить свои, @jsotola

тогда вы должны предположить, что ISR никогда не вызывается.....может это поможет......http://www.instructables.com/id/Arduino-Timer-Interrupts/, @jsotola

Примечание: 0b101 << CS00 выглядит как плохой код. Лично; Я бы использовал (1 << CS00) | (1 << CS02), @Gerben


1 ответ


1

Я нашел ответ здесь: https://www.avrfreaks.net/ форум/atmega32u4-arduino-leonardo-strange-timer-behavior

Похоже, что соединение USB генерирует прерывания с более высоким приоритетом. Я до сих пор не знаю, почему прерывания работают на более высокой частоте.

Решения включают питание платы от зарядного устройства USB или другого источника питания, а не через USB компьютера, или добавление следующего кода перед разрешением прерывания:

// Очистить флаги прерывания usb
USBINT = 0;
UDINT  = 0;
for (uint8_t i = 0; i < 6; i++)
{ // Для каждой конечной точки USB
    UENUM = i; // выбираем _i-ю конечную точку
    UEINTX = UEIENX = 0; // Очистить флаги прерывания для этой конечной точки
}

Спасибо тем, кто мне помог!

,

Я думаю, что обработчик прерывания отсутствует при выходе из загрузчика, поэтому avr-gcc по умолчанию сбрасывает плату, что может привести к более высокой частоте включения светодиода , в то время как при более низкой частоте плата сбрасывается до первого прерывания., @Simon Tagne