Timer3 im CTC-Modus einstellen - Konflikt mit der Servobibliothek

10

Ich möchte einen Timer einrichten, um eine Funktion 800 Mal pro Sekunde aufzurufen. Ich verwende Arduino Mega und Timer3 mit einem Prescaler von 1024. Um den Prescaler-Faktor auszuwählen, habe ich die folgenden Schritte berücksichtigt:

  • CPU-Frequenz: 16 MHz
  • Timer-Auflösung: 65536 (16 Bit)
  • Dividieren CPU freq durch den gewählten Vorteiler: 16x10 ^ 6/ 1024 = 15625
  • Teilen Sie den Rest durch die gewünschte Frequenz 62500/800 = 19 .
  • Tragen Sie das Ergebnis + 1 in das OCR3-Register ein.

Ich habe die folgende Tabelle verwendet, um Register von TCCR3B zu setzen:

Geben Sie hier die Bildbeschreibung ein

Der Fehler

Es ist unmöglich, den Code zu kompilieren. Dies ist der vom Compiler zurückgegebene Fehler:

Servo \ Servo.cpp.o: In der Funktion '__vector_32': C: \ Programme (x86) \ Arduino \ Bibliotheken \ Servo / Servo.cpp: 110: Mehrfachdefinition von '__vector_32' AccelPart1_35.cpp.o: C: \ Programmdateien (x86) \ Arduino / AccelPart1_35.ino: 457: hier zuerst definiert c: / Programme (x86) / arduino / hardware / tools / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe: Entspannung deaktivieren: Es funktioniert nicht mit mehreren Definitionen

Der Code

volatile int cont = 0;
unsigned long aCont = 0;
void setup()
{
 [...]
  // initialize Timer3
  cli();          // disable global interrupts
  TCCR3A = 0;     // set entire TCCR3A register to 0
  TCCR3B = 0;     // same for TCCR3B

  // set compare match register to desired timer count: 800 Hz
  OCR3A = 20;
  // turn on CTC mode:
  TCCR3B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // enable timer compare interrupt:
  TIMSK3 |= (1 << OCIE3A);
  // enable global interrupts:
  sei();
}

void loop()
{
 // Print every second the number of ISR invoked -> should be 100
 if ( millis() % 1000 == 0)
 {
   Serial.println();
   Serial.print(" tick: ");
   Serial.println(contatore);
   contatore = 0;
 }
}

[...]

// This is the 457-th line
ISR(TIMER3_COMPA_vect)
{
    accRoutine();
    contatore++;
}

void accRoutine()
{
  // reads analog values
}

Wie kann man den Konflikt mit der Servobibliothek lösen?

LÖSUNG

Konflikt mit dem folgenden Code gelöst. Es wird kompiliert, aber der dem 800-Hz-Timer zugeordnete Zähler erhöht seinen Wert nicht.

volatile int cont = 0;

void setup()
{
  Serial.begin(9600);
  // Initialize Timer
  cli();          // disable global interrupts
  TCCR3A = 0;     // set entire TCCR3A register to 0
  TCCR3B = 0;     // same for TCCR3B

  // set compare match register to desired timer count: 800 Hz
  OCR3B = 20;
  // turn on CTC mode:
  TCCR3B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // enable timer compare interrupt:
  TIMSK3 |= (1 << OCIE3B);
  // enable global interrupts:
  sei();

  Serial.println("Setup completed");
}

void loop()
{
  if (millis() % 1000 == 0)
  {
    Serial.print(" tick: ");
    Serial.println(cont);
    cont = 0;
  }
}

ISR(TIMER3_COMPB_vect)
{
  cont++;
}

Da das Hauptproblem gelöst ist, habe ich noch eine Frage erstellt hier , um das Problem der Zähler Inkrementierung bezogen.

UserK
quelle
Verwenden Sie die Servobibliothek in Ihrem Programm oder nicht?
Jfpoilpret
2
Servo.cpp wahrscheinlich auch ISR (TIMER3_COMPA_vect)
TMa
1
Verwenden Sie stattdessen einfach Timer1, 4 oder 5.
Gerben
1
Servo definiert Interrupt-Funktionen für die Timer 1,3,4 und 5 auf Megas für COMPA. Wie wäre es mit COMPB?
BrettAM
1
Du hast recht . Sie verschlingen nur alle Timer. Ich denke, Sie müssen die Bibliothek leicht ändern, indem Sie die #define _useTimer3Zeile entfernen , oder versuchen, #undef _useTimer3nach dem Include ein Recht zu setzen .
Gerben

Antworten:

4

Leider reserviert die Servobibliothek den Ausgangsvergleich A (OCR * A) auf den Timern 1,3,4 und 5, wenn sie auf ein Arduino-Mega geladen wird. Jeder kann nur einen ISR haben, sodass Sie während der Verwendung von Servo keinen eigenen TIMER * _COMPA_vect definieren können, ohne die Bibliothek zu ändern.

Jeder Hardware-Timer ist jedoch mit 2 Ausgangsvergleichsregistern ausgestattet. Servo beansprucht keine TIMER * _COMPB_vect-Interrupts, daher können diese kostenlos verwendet werden und funktionieren genauso.

Sie sollten auf die Aktivitäten der Servobibliotheken achten, da dies die Konfiguration Ihres Timers ändern kann. Die Standardreihenfolge für Megas ist 5,1,3,4 und für jeweils 12 Servos. Der Timer wird erst konfiguriert, wenn er benötigt wird. Daher sollten Sie Timer 3 verwenden, bis Sie das 25. Servo hinzufügen.

Verwenden Sie zum Ändern Ihres Codes OCR3B anstelle von OCR3A (den Ausgangsvergleichsregistern) und setzen Sie das Bit OCIE3B anstelle von OCIE3A in TIMSK3 (die Ausgangsvergleichsunterbrechungsaktivierungsbits). Dann ändern Sie Ihre ISR-Funktion auf ISR(TIMER3_COMPB_vect){}

Der CTC-Modus funktioniert nur mit OCR3A. Wenn Sie jedoch TCNT3 in Ihrer Interrupt-Funktion auf 0 setzen, können Sie ein ähnliches Verhalten erzielen. Denken Sie daran, die Leitung zu entfernen, die den CTC-Modus mit WGM12 aktiviert.

BrettAM
quelle
OK danke! Irgendwelche Ratschläge zur Inkrementierung des Zählers ?
UserK