Atmel / Arduino: ISR (TIMER0_OVF_vect) не будет компилироваться («впервые определено» в __vector_16)

В настоящее время я работаю над ШИМ-модулятором для «симуляции» коммутации зажигания двигателя автомобиля. Затем я буду использовать его для управления другим микроконтроллером, который обрабатывает преобразование необработанного сигнала (коммутатора двигателя) в чистое выходное напряжение, проходящее через гальванометр счетчика числа оборотов в минуту.

Этот проект также является для меня предлогом, чтобы научиться лучше контролировать мой микроконтроллер.

Итак, я написал небольшую программу, использующую timer0 (8 бит), и мне нужно вызвать две подпрограммы обработки прерываний (ISR):

  • TIMER0_OVF_vect: прерывание переполнения
  • TIMER0_COMPA_vect: срабатывает при сравнении

У меня есть следующие функции:

void configureTimer0(parameters)
{
cli();

// Some maths
TCCR0A = (1<<WGM01) | (1<<WGM00); // I tried to use the "Fast PWM" waveform generation mode
TCCR0B &= 0b00110000; // 5th and 4th bits are reserved. Every other bits is set to 0.
TCNT0 = 0; // Initialize counter value to 0

TCCR0B |= select_prescaler(prescaler); // Custom function to determine the right prescaler
OCR0A = ext_OnTicks; // Output compare register is set to a predetermined numbers of ticks

// Enabling overflows interrupt:
TIMSK0 |= (1 << TOIE0);
sei(); // Enable interrupts
}

Затем при определенных условиях я включаю и выключаю бит OCIE0 в TIMSK0 в зависимости от ситуации.
Однако прерывание переполнения всегда включено.

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

"C:\Users\UTILIS~1\AppData\Local\Temp\arduino_build_8383\sketch\PWM_modulator.ino.cpp.o" "C:\Users\UTILIS~1\AppData\Local\Temp\arduino_build_8383/..\arduino_cache_395570\core\core_arduino_avr_uno_a94ab6aaf61dfb93b4a8079c694a14c2.a" "-LC:\Users\UTILIS~1\AppData\Local\Temp\arduino_build_8383" -lm
wiring.c.o (symbol from plugin): In function `__vector_16':

(.text+0x0): multiple definition of `__vector_16'

C:\Users\UTILIS~1\AppData\Local\Temp\arduino_build_8383\sketch\PWM_modulator.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

exit status 1
Erreur de compilation pour la carte Arduino/Genuino Uno // Compilation error for Uno board (French)

Я попытался скомпилировать с ISR (TIMER0_COMPB_vect) вместо ISR (TIMER0_OVF_vect), и это работает, но на самом деле это не главное для моей программы.

Я также попробовал ISR (TIMER2_OVF_vect), который также является 8-битным таймером. Я мог бы синхронизировать Timer0 и Timer2 для достижения желаемого эффекта, однако я не думаю, что это достаточно чисто (и это мешает мне использовать возможности Timer2).

В моем коде что-то не так, но я не могу понять, где скрывается ошибка.
С файлом wiring.c.o определенно что-то связано.

PS: я долго искал решение с тех пор, как появилась проблема, но я не мог найти способ правильно задать вопрос ни Google, ни сайту переполнения стека.
Извиняюсь, если я пропустил правильную строку поиска!

1

Решение

Это является Можно предоставить свой собственный обработчик для Timer0 и по-прежнему использовать среду Arduino.

Это делается путем (необязательно) отключения существующего обработчика для Timer0 в файле wiring.c (внутри установки Arduino). Положить в условный сборник, #ifndef / #endifвокруг существующего обработчика:

#ifndef _DISABLE_ARDUINO_TIMER0_INTERRUPT_HANDLER_

#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;

m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}

timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}

#endif

Например, в Windows, файл wiring.c может находиться в папке C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino,

Обратите внимание, что может потребоваться наличие прав администратора для внесения изменений в wiring.c, В Windows это можно сделать, щелкнув правой кнопкой мыши на текстовом редакторе (текстовом редакторе, который может обрабатывать символы конца строки Unix — Блокнот на самом деле не может это обработать) и выбрав «Запуск от имени администратора».

Затем в исходном коде поместите эти две строки вверху файла:

#define _DISABLE_ARDUINO_TIMER0_INTERRUPT_HANDLER_

#include <wiring.c>

Обратите внимание, что для других проектов Arduino он работает точно так же, как и раньше. Обработчик прерываний отключен только если символ препроцессора _DISABLE_ARDUINO_TIMER0_INTERRUPT_HANDLER_ определено.

Та же процедура может быть применена к TIMER0_COMPA_vect также (файл Tone.cpp в той же папке).

Это было протестировано с помощью Arduino Uno, Arduino IDE 1.8.5, текстовый редактор UltraEdit, и Windows 10.

3

Другие решения

Вы используете библиотеку Arduino, которая уже определяет обработчик для TIMER0_OVF прерывание.

Если вы хотите определить свой собственный обработчик для этого прерывания, вам нужно будет построить свой проект автономно, без использования библиотеки или инструментов Arduino.

1

Я просто использовал Timer2 вместо Timer0. Используя Timer2, я все еще могу установить переполнение И прерывания сравнения вывода на том же таймере, как и ожидалось.

Это довольно простой способ обойти эту проблему, однако он может не подходить для всех случаев. Возможно, мне придется переделать мой код и адаптировать его к прямому процессу компиляции avr-gcc / Atmel Studio.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector