Définition de timer3 en mode CTC - conflit avec la bibliothèque de servomoteurs

10

Je voudrais configurer une minuterie afin d'appeler une fonction 800 fois par seconde. J'utilise l'Arduino Mega et Timer3 avec un pré-échelle de 1024. Pour choisir le facteur de pré-échelle, j'ai considéré les étapes suivantes:

  • Fréquence du processeur: 16 MHz
  • Résolution de la minuterie: 65536 (16 bits)
  • Diviser freq du processeur par l'étage d' adaptation choisi: 16x10 ^ 6/ 1024 = 15625
  • Divisez le reste à la fréquence souhaitée 62500/800 = 19 .
  • Mettez le résultat + 1 dans le registre OCR3.

J'ai utilisé le tableau suivant pour définir les registres de TCCR3B:

entrez la description de l'image ici

L'erreur

Il est impossible de compiler le code. C'est l'erreur retournée par le compilateur:

Servo \ Servo.cpp.o: Dans la fonction '__vector_32': C: \ Program Files (x86) \ Arduino \ bibliothèques \ Servo / Servo.cpp: 110: définition multiple de '__vector_32' AccelPart1_35.cpp.o: C: \ Program Files (x86) \ Arduino / AccelPart1_35.ino: 457: d'abord défini ici c: / program files (x86) / arduino / hardware / tools / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe: Désactiver la relaxation: cela ne fonctionnera pas avec plusieurs définitions

Le 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
}

Comment résoudre le conflit avec la bibliothèque de servomoteurs?

SOLUTION

Conflit résolu en utilisant le code suivant. Il compile mais le compteur associé au temporisateur 800Hz n'incrémente pas sa valeur.

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

Depuis que le problème principal a été résolu, j'ai créé ici une autre question liée au problème de l'incrémentation du compteur.

UserK
la source
Utilisez-vous ou non la bibliothèque de servos dans votre programme?
jfpoilpret
2
Servo.cpp probable aussi ISR (TIMER3_COMPA_vect)
TMa
1
Utilisez simplement Timer1, 4 ou 5 à la place.
Gerben
1
Le servo définit les fonctions d'interruption pour les temporisateurs 1, 3, 4 et 5 sur les mégas pour COMPA. Que diriez-vous d'utiliser COMPB?
BrettAM
1
Tu as raison . Ils monopolisent tous les chronomètres. Je suppose que vous devez modifier légèrement la bibliothèque en supprimant la #define _useTimer3ligne, ou essayez de mettre un #undef _useTimer3droit après l'inclusion.
Gerben

Réponses:

4

Malheureusement, la bibliothèque Servo réserve la sortie comparer A (OCR * A) sur les minuteries 1,3,4 et 5 lorsqu'elle est chargée sur un méga Arduino. Chacun ne peut avoir qu'un seul ISR, vous ne pourrez donc pas définir votre propre TIMER * _COMPA_vect pendant que vous utilisez Servo sans modifier la bibliothèque.

Cependant, chaque temporisateur matériel est équipé de 2 registres de comparaison de sortie. Le servo ne revendique aucune interruption TIMER * _COMPB_vect, donc celles-ci sont libres d'utiliser et fonctionnent exactement de la même manière.

Vous devez faire attention aux activités des bibliothèques de servomoteurs, cela pourrait changer la configuration de votre minuterie. L'ordre par défaut sur les mégas est de 5,1,3,4 et de donner chacun 12 servos. Il ne configure la minuterie qu'une fois qu'il en a besoin, vous devriez donc bien utiliser la minuterie 3 jusqu'à ce que vous ajoutiez ce 25ème servo.

Pour modifier votre code, utilisez OCR3B au lieu d'OCR3A (les registres de comparaison de sortie) et définissez le bit OCIE3B au lieu d'OCIE3A dans TIMSK3 (les bits d'activation d'interruption de comparaison de sortie). Ensuite, vous changez votre fonction ISR en ISR(TIMER3_COMPB_vect){}

Le mode CTC ne fonctionne qu'avec OCR3A, mais si vous définissez TCNT3 sur 0 dans votre fonction d'interruption, vous pouvez obtenir un comportement similaire. N'oubliez pas de supprimer la ligne qui active le mode CTC à l'aide de WGM12.

BrettAM
la source
OK merci! Un conseil sur l'incrémentation du compteur ?
UserK