Atmel / Arduino:ISR(TIMER0_OVF_vect) 无法编译("first defined" in __vector_16)
Atmel / Arduino: ISR(TIMER0_OVF_vect) won't compile ("first defined" in __vector_16)
我目前正在研究用于 "simulate" 汽车发动机点火换向的 PWM 调制器。然后,我将使用它来驱动另一个微控制器,该微控制器处理从原始信号(发动机换向器)到干净输出电压的转换,通过 RPM 计数器的电流计。
这个项目也是我学习如何更好地控制我的微控制器的借口。
嗯,我写了一个小程序,使用timer0(8位),我需要触发两个中断服务程序(ISRs):
- 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
}
然后在一定条件下,我根据情况将TIMSK0中的OCIE0位开关。
但是,溢出中断始终处于启用状态。
当我尝试编译时,我遇到了这些错误:
"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 Stack Overflow 站点。
如果我错过了正确的搜索字符串,我们深表歉意!
您正在使用 Arduino 库,它已经为 TIMER0_OVF
中断定义了一个处理程序。
如果您想为此中断定义自己的处理程序,则需要独立构建项目,而无需使用 Arduino 库或工具。
我只是用了 Timer2 而不是 Timer0。使用 Timer2,我仍然可以像预期的那样在同一定时器上设置溢出和输出比较中断。
这是解决此问题的一种相当简单的方法,但它可能并不适合所有情况。我可能需要修改我的代码并使其适应直接的 avr-gcc / Atmel Studio 编译过程。
可以为 Timer0 提供您自己的处理程序并仍然使用 Arduino 环境。
这是通过(可选)禁用文件 wiring.c
(在 Arduino 安装内)中 Timer0 的现有处理程序来完成的。在现有处理程序周围放入条件编译,#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 上,这是通过右键单击文本编辑器(文本编辑器,如 Notepad++ or UltraEdit[1],可以处理 Unix 结束-行字符 - 记事本无法真正处理这个)并选择 "Run as Adminstrator".
然后,在您的源代码中将这两行放在文件的顶部:
#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.
进行测试的
1.我也希望 Visual Studio Code 可以工作,但我还没有测试过。
我目前正在研究用于 "simulate" 汽车发动机点火换向的 PWM 调制器。然后,我将使用它来驱动另一个微控制器,该微控制器处理从原始信号(发动机换向器)到干净输出电压的转换,通过 RPM 计数器的电流计。
这个项目也是我学习如何更好地控制我的微控制器的借口。
嗯,我写了一个小程序,使用timer0(8位),我需要触发两个中断服务程序(ISRs):
- 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
}
然后在一定条件下,我根据情况将TIMSK0中的OCIE0位开关。 但是,溢出中断始终处于启用状态。
当我尝试编译时,我遇到了这些错误:
"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 Stack Overflow 站点。 如果我错过了正确的搜索字符串,我们深表歉意!
您正在使用 Arduino 库,它已经为 TIMER0_OVF
中断定义了一个处理程序。
如果您想为此中断定义自己的处理程序,则需要独立构建项目,而无需使用 Arduino 库或工具。
我只是用了 Timer2 而不是 Timer0。使用 Timer2,我仍然可以像预期的那样在同一定时器上设置溢出和输出比较中断。
这是解决此问题的一种相当简单的方法,但它可能并不适合所有情况。我可能需要修改我的代码并使其适应直接的 avr-gcc / Atmel Studio 编译过程。
可以为 Timer0 提供您自己的处理程序并仍然使用 Arduino 环境。
这是通过(可选)禁用文件 wiring.c
(在 Arduino 安装内)中 Timer0 的现有处理程序来完成的。在现有处理程序周围放入条件编译,#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 上,这是通过右键单击文本编辑器(文本编辑器,如 Notepad++ or UltraEdit[1],可以处理 Unix 结束-行字符 - 记事本无法真正处理这个)并选择 "Run as Adminstrator".
然后,在您的源代码中将这两行放在文件的顶部:
#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.
进行测试的1.我也希望 Visual Studio Code 可以工作,但我还没有测试过。