2017-10-04 137 views
1

我目前工作的一個PWM調製器以「模擬」汽車發動機點火減刑。然後,我將使用它來驅動另一個處理從原始信號(引擎的換向器)轉換爲乾淨輸出電壓的微控制器,並通過RPM計數器的檢流計。愛特梅爾/ Arduino的:ISR(TIMER0_OVF_vect)將無法編譯(「第一定義」中__vector_16)

這個項目對我來說也是學習如何有在我的微控制器更好的控制的藉口。

嗯,我寫了一個小程序,用定時器0(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位置ON和OFF。 但是,溢出中斷始終處於啓用狀態。

當我嘗試編譯,我結束了這些錯誤:

"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站點。 道歉,如果我錯過了正確的搜索字符串!

+0

它看起來像處理'ISR(TIMER0_OVF_vect)測試'在多個地方被定義。 –

回答

1

您使用Arduino的庫,它已經定義了TIMER0_OVF中斷處理程序。

如果要定義自己的處理程序爲這個中斷,您將需要建立項目獨立,不使用Arduino的庫或工具。

+0

這是真的......所以這主要是由於Arduino庫?我不認爲我必須這麼早地跳到avr-gcc和avr工具鏈,但無論如何它必須嘗試!謝謝您的回覆! – bebenlebricolo

0

我只是使用Timer2而不是Timer0。使用Timer2,我仍然可以設置一個溢出和一個輸出比較中斷在同一個計時器,正如所料。

這是一種解決此問題的相當簡單的方法,但它可能不適合所有情況。我可能需要重寫我的代碼,並將其調整爲直接avr-gcc/Atmel Studio編譯過程。

1

可能爲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上,通過右鍵單擊文本編輯器(一個可以處理Unix行尾字符的文本編輯器 - 記事本無法真正處理此操作)並選擇「以管理員身份運行」來完成此操作。

然後,在你的源代碼放在這兩條線在文件的頂部:

#define _DISABLE_ARDUINO_TIMER0_INTERRUPT_HANDLER_ 

#include <wiring.c> 

注意,其他的Arduino項目是完全按照以前的作品。如果定義了預處理器符號_DISABLE_ARDUINO_TIMER0_INTERRUPT_HANDLER_,則只能禁用中斷處理程序。

同樣的過程可能也必須應用於TIMER0_COMPA_vect(文件Tone.cpp在同一文件夾中)。

這與一個Arduino烏諾等同,Arduino的IDE 1.8.5,文本編輯器UltraEdit,和Windows 10

+0

非常感謝您的回覆。自從我問到這些問題以來,我就深入到Atmel Studio以及優化和模擬的神奇之處。現在對我來說更清楚了。我一定會用你的竅門來做只有arduino的程序,它可以幫助你節省大量的時間/精力(重新設計一個使用Timer1代替Timer0的程序可能會很痛苦)。 – bebenlebricolo

+0

@bebenlebricolo:我發現了一種不切實際的方式來做到這一點(所以其他Arduino項目不受文件'wiring.c'中的變化影響)。我已經更新了我的答案。 (我在爲精確的8MHz頻率計數器編寫軟件時遇到了同樣的問題(不需要外部元件),我必須使用Timer0和Timer1,利用這兩個硬件計數器,使用Timer0輸入信號Timer2被用於1.14285714286 MHz的測試信號。) –

+0

@bebenlebricolo:哇!我剛剛發現[Arduino Uno使用陶瓷諧振器](https://learn.adafruit.com/arduino-tips-tricks-and-techniques/arduino-uno-faq)(+/- 0.5%),而不是晶體振盪器(PCB上有一個晶體振盪器,但是用於USB芯片)。陶瓷諧振器在工作中受到了不好的經歷(由第三方供應商使用)。頻率計數器的最終版本將用於帶有晶體振盪器的裸露ATmega328芯片(以及後來的基於DCF77的頻率參考)。 –