J'essaie de vérifier la fréquence de Timer3 à l'aide d'un compteur. La valeur du compteur, déclarée volatile, est incrémentée dans l'ISR et chaque seconde la somme est affichée dans la boucle principale et la valeur remise à zéro.
La minuterie a été correctement configurée. (Si je choisis une minuterie à 3 Hz, je peux voir le voyant clignoter)
Le problème
Le compteur n'est pas incrémenté. Voici la sortie:
Setup Completed
tick: 1
tick: 0
tick: 0
tick: 0
CODE
volatile int cont = 0;
void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT);
// 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; // 800Hz 5; // 3 Hz
// 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)
{
//digitalWrite(13, digitalRead(13) ^ 1);
cont++;
}
EDIT Ce temporisateur est utilisé pour lire une valeur de journal d'un accéléromètre et la stocker dans un tableau de float. Mais pour le moment, je suis bloqué sur ce problème de mise à jour.
SOLUTION 1 Merci à Gerben
volatile int cont = 0;
void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT);
// 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
OCR3A = 20; // 20; //800Hz 5; // 3 Hz
// turn on CTC mode:
TCCR3B |= (1 << WGM32);
// 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()
{
delay(1000);
Serial.println(cont);
cont = 0;
}
ISR(TIMER3_COMPB_vect)
{
cont++;
}
SOLUTION 2 Merci à BrettM
volatile int cont = 0;
void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT);
// 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; //800Hz 5; // 3 Hz
// turn on CTC mode:
//TCCR3B |= (1 << WGM32);
// 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()
{
Serial.println(cont);
cont = 0;
delay(1000);
}
ISR(TIMER3_COMPB_vect)
{
TCNT3 = 0;
cont++;
}
digitalWrite
ligne, vous voyez la LED clignoter environ une fois par seconde (toutes les 0,66s)?digitalWrite
et queOCR3B = 5;
le voyant clignote à environ cette fréquence.cont = 0;
intérieur de la boucle? Que se passe-t-il alors?Réponses:
En mode CTC, le top n'est
OCR3A
pasOCR3B
!Après cela
TIMSK3 |= (1 << OCIE3B);
devrait également être changé àTIMSK3 |= (1 << OCIE3A);
, etISR(TIMER3_COMPB_vect)
àISR(TIMER3_COMPA_vect)
Pour 3Hz,
OCR3A
devrait être 5208, pas 20.Techniquement
TCCR3B |= (1 << WGM12);
devrait êtreTCCR3B |= (1 << WGM32);
la source
TIMSK3 |= (1 << OCIE3B);
. Merci Gerben! Veuillez modifier votre réponse et je l'accepterai comme solution.ISR(TIMER3_COMPB_vect)
devrait êtreISR(TIMER3_COMPA_vect)
. Si un ISR n'est pas défini, l'AVR se réinitialisera, comme vous le faisiez. Heureux que tu es parvenu à le faire fonctionner.Il semble que ma réponse à cette question était auparavant incomplète, merci d'avoir souligné que le mode CTC ne fonctionne qu'avec OCR3A Gerben. Je m'excuse de ne pas avoir testé une réponse avant de la poster.
Étant donné les informations contenues uniquement dans cette question, la réponse de Gerben est complète, mais comme votre autre question implique que vous ne pouvez pas utiliser OCR3A en raison de la bibliothèque de servomoteurs, j'ajouterai un peu. (J'ai également modifié cette réponse)
vous pouvez émuler le comportement du mode CTC en définissant TCNT3 sur 0 dans votre routine d'interruption. N'oubliez pas de supprimer la ligne qui active le mode CTC dans votre code.
J'ai testé votre code avec cet ISR:
et cette configuration des registres de temporisation
Cela pourrait être un peu moins précis aux hautes fréquences que le CTC, je ne suis pas sûr, mais à 3 Hz, cela fonctionnait parfaitement. Notez que 5208 était la valeur OCR correcte, pas 20 (encore une fois grâce à Gerben).
la source
TCNT3=0;
dans l'ISR () et supprimé//TCCR3B |= (1 << WGM32);
dans le setup () comme vous l'avez dit. J'ai également essayé de commenter lacont=0;
ligne, mais rien n'a changéprintln(cont); delay(1000);
. Aussi, vous incluez toujours les bits avec cli () et TCCR3A, etc. correct?