代码之家  ›  专栏  ›  技术社区  ›  bebenlebricolo

Atmel/Arduino:ISR(TIMER0\u OVF\u vect)不会编译(“第一个定义”在_uvector\u 16中)

  •  1
  • bebenlebricolo  · 技术社区  · 7 年前

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

    我用定时器0(8位)编写了一个小程序,需要触发两个中断服务例程(ISR):

    • 定时器0\u OVF\u vect:溢出中断
    • 定时器0\u COMPA\u 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\u COMPB\u vect)而不是ISR(TIMER0\u OVF\u vect)编译,这是可行的,但实际上这不是我程序的重点。

    我的代码中有一些错误,但无法理解错误隐藏在哪里。 这肯定与接线有关。c、 o文件。

    PS:自从问题出现以来,我已经寻找了很长时间的解决方案,但我找不到任何方法正确地询问谷歌,也没有找到堆栈溢出站点。 抱歉,如果我错过了正确的搜索字符串!

    3 回复  |  直到 7 年前
        1
  •  4
  •   Peter Mortensen icecrime    5 年前

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

    这是通过(可选)禁用文件中计时器0的现有处理程序来实现的 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上,文件 装电线。c 可能位于文件夹中 C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino

    请注意,可能需要具有管理权限才能更改 装电线。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 在同一文件夹中)。

    UltraEdit ,以及Windows10。

    1、我也希望 Visual Studio Code 但我还没有测试过。

        2
  •  1
  •   user149341 user149341    7 年前

    您正在使用Arduino库,它已经为 TIMER0_OVF 打断

    如果您想为这个中断定义自己的处理程序,则需要独立构建项目,而不使用Arduino库或工具。

        3
  •  0
  •   Peter Mortensen icecrime    7 年前

    我只是使用了Timer2而不是Timer0。使用Timer2,我仍然可以像预期的那样在同一个计时器上设置溢出和输出比较中断。