c++ - 爱特梅尔/Arduino : ISR(TIMER0_OVF_vect) won't compile ("first defined" in __vector_16)

标签 c++ c interrupt atmel avr-gcc

我目前正在开发 PWM 调制器来“模拟”汽车发动机点火换向。然后,我将用它来驱动另一个微 Controller ,该微 Controller 通过 RPM 计数器的检流计处理从原始信号(发动机换向器)到干净输出电压的转换。

这个项目也是我学习如何更好地控制我的微 Controller 的一个借口。

嗯,我写了一个小程序,使用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
}

然后,在某些条件下,我根据情况打开和关闭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网站。 如果我错过了正确的搜索字符串,请道歉!

最佳答案

可以为 Timer0 提供您自己的处理程序,并且仍然使用 Arduino 环境。

这是通过(可选)禁用文件 wiring.c 中 Timer0 的现有处理程序来完成的。 (在 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 上,这是通过右键单击文本编辑器(文本编辑器,如 Notepad++UltraEdit [1],可以处理 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。

<子>1。我也期望 Visual Studio Code可以工作,但我还没有测试过。

关于c++ - 爱特梅尔/Arduino : ISR(TIMER0_OVF_vect) won't compile ("first defined" in __vector_16),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46573550/

相关文章:

c - 修复内存泄漏

c - 如何编写UART0接收和发送中断

c - linux 实时调度任务时出现运行时错误?

debugging - 可以在 OSR 中使用断点吗?

c++ - 离散傅立叶变换的实现 - FFT

c++ - C++ list.erase(it, it) 是否删除某些东西?在哪里可以找到好的引用资料?

java - 这个变量如何在 cpp 中用作 int 和数组?

c++ - 结构和类层次结构(制作模板)

c - 了解 C 中的内存对齐约束和填充字节

c - c中分配给矩阵的最大大小