Ustawienie timera 3 w trybie CTC - konflikt z biblioteką serw


10

Chciałbym ustawić timer, aby wywoływał funkcję 800 razy na sekundę. Używam Arduino Mega i Timera 3 z preskalerem 1024. Aby wybrać współczynnik preskalera, wziąłem pod uwagę następujące kroki:

  • Częstotliwość procesora: 16 MHz
  • Rozdzielczość timera: 65536 (16 bitów)
  • Podzielić przez procesor przenoszenia wybranego dzielnikiem: 16x10 d6 / 1024 = 15625
  • Podziel resztę przez żądaną częstotliwość 62500/800 = 19 .
  • Umieść wynik + 1 w rejestrze OCR3.

Użyłem poniższej tabeli, aby ustawić rejestry TCCR3B:

wprowadź opis zdjęcia tutaj

Błąd

Nie można skompilować kodu. Jest to błąd zwracany przez kompilator:

Servo \ Servo.cpp.o: W funkcji '__vector_32': C: \ Program Files (x86) \ Arduino \ libraries \ Servo / Servo.cpp: 110: wiele definicji „__vector_32” AccelPart1_35.cpp.o: C: \ Pliki programów (x86) \ Arduino / AccelPart1_35.ino: 457: po raz pierwszy zdefiniowano tutaj c: / pliki programów (x86) / arduino / hardware / tools / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe: Wyłączanie relaksacji: nie będzie działać z wieloma definicjami

Kod

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
}

Jak rozwiązać konflikt z biblioteką serwomechanizmów?

ROZWIĄZANIE

Konflikt rozwiązany za pomocą następującego kodu. Kompiluje się, ale licznik związany z zegarem 800 Hz nie zwiększa jego wartości.

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++;
}

Ponieważ główny problem został rozwiązany, stworzyłem tutaj kolejne pytanie związane z problemem przyrostu licznika.


Czy korzystasz z biblioteki serwo w swoim programie, czy nie?
jfpoilpret

2
Prawdopodobnie Servo.cpp ma również ISR (TIMER3_COMPA_vect)
TMa

1
Zamiast tego użyj Timera 1, 4 lub 5.
Gerben,

1
Serwo definiuje funkcje przerwania dla timerów 1, 3, 4 i 5 w megas dla COMPA. Co powiesz na korzystanie z COMPB?
BrettAM,

1
Masz rację . Po prostu odmierzają wszystkie liczniki. Myślę, że musisz nieco zmodyfikować bibliotekę, usuwając #define _useTimer3wiersz lub spróbuj wstawić #undef _useTimer3zaraz po dołączeniu.
Gerben,

Odpowiedzi:


4

Niestety, biblioteka Servo rezerwuje dane wyjściowe porównania A (OCR * A) na zegarach 1,3,4 i 5, gdy są załadowane na arduino mega. Każdy może mieć tylko jeden ISR, więc nie będziesz mógł zdefiniować własnego TIMERA * _COMPA_vect podczas korzystania z Serwomechanizmu bez modyfikacji biblioteki.

Jednak każdy sprzętowy zegar jest wyposażony w 2 rejestry porównania wyjściowej. Serwo nie żąda żadnych przerwań TIMER * _COMPB_vect, więc są one bezpłatne i działają dokładnie tak samo.

Należy uważać na działania bibliotek Servo, może to zmienić konfigurację timera. Domyślna kolejność na mega to 5,1,3,4 i daje każdemu 12 serwomechanizmów. Konfiguruje timer tylko wtedy, gdy go potrzebuje, więc powinieneś dobrze korzystać z timera 3, dopóki nie dodasz 25-tego serwomechanizmu.

Aby zmienić kod, użyj OCR3B zamiast OCR3A (Rejestry porównania wyjściowej) i ustaw bit OCIE3B zamiast OCIE3A w TIMSK3 (Przerwanie porównania wyjścia Włącz bity). Następnie zmień funkcję ISR na ISR(TIMER3_COMPB_vect){}

Tryb CTC działa tylko z OCR3A, ale jeśli ustawisz TCNT3 na 0 w funkcji przerwania, możesz uzyskać podobne zachowanie. Pamiętaj, aby usunąć linię, która włącza tryb CTC przy użyciu WGM12.


Ok dzięki! Wszelkie porady na temat zwiększenia licznika ?
UżytkownikK
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.