Ich versuche die Frequenz von Timer3 mit einem Zähler zu überprüfen. Der als flüchtig deklarierte Wert des Zählers wird im ISR inkrementiert und jede Sekunde wird die Summe in der Hauptschleife angezeigt und der Wert auf Null zurückgesetzt.
Der Timer wurde korrekt eingestellt. (Wenn ich einen 3-Hz-Timer wähle, kann ich sehen, dass die LED blinkt.)
Das Problem
Der Zähler wird nicht erhöht. Hier ist die Ausgabe:
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++;
}
BEARBEITEN Dieser Timer wird verwendet, um einen Anlog-Wert von einem Beschleunigungsmesser zu lesen und in einem Array von float zu speichern. Aber im Moment bin ich bei diesem Update-Problem festgefahren.
LÖSUNG 1 Danke an 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++;
}
LÖSUNG 2 Dank an 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
Zeile auskommentieren, blinkt die LED etwa einmal pro Sekunde (alle 0,66 s)?digitalWrite
undOCR3B = 5;
auf ungefähr diese Frequenz blinke.cont = 0;
innerhalb der Schleife? Was passiert dann?Antworten:
Im CTC-Modus ist die Spitze
OCR3A
nichtOCR3B
!Danach
TIMSK3 |= (1 << OCIE3B);
sollte auch geändert werdenTIMSK3 |= (1 << OCIE3A);
, undISR(TIMER3_COMPB_vect)
zuISR(TIMER3_COMPA_vect)
Für 3Hz
OCR3A
sollte 5208 sein, nicht 20.Technisch
TCCR3B |= (1 << WGM12);
sollte seinTCCR3B |= (1 << WGM32);
quelle
TIMSK3 |= (1 << OCIE3B);
. Danke Gerben! Bitte ändern Sie Ihre Antwort und ich werde sie als Lösung akzeptieren.ISR(TIMER3_COMPB_vect)
sollte seinISR(TIMER3_COMPA_vect)
. Wenn kein ISR definiert ist, wird der AVR wie von Ihnen selbst zurückgesetzt. Ich bin froh, dass du es zum Laufen gebracht hast.Es scheint, dass meine Antwort auf diese Frage zuvor unvollständig war, danke für den Hinweis, dass der CTC-Modus nur mit OCR3A Gerben funktioniert. Ich entschuldige mich dafür, dass ich eine Antwort nicht getestet habe, bevor ich sie poste.
Angesichts der Informationen nur in dieser Frage ist Gerbens Antwort vollständig, aber da Ihre andere Frage impliziert, dass Sie OCR3A aufgrund der Servobibliothek nicht verwenden können, werde ich ein wenig hinzufügen. (Ich habe diese Antwort auch bearbeitet)
Sie können das Verhalten des CTC-Modus emulieren, indem Sie TCNT3 in Ihrer Interrupt-Routine auf 0 setzen. Denken Sie daran, die Zeile zu entfernen, die den CTC-Modus in Ihrem Code aktiviert.
Ich habe Ihren Code mit diesem ISR getestet:
und diese Konfiguration der Zeitgeberregister
Ich bin mir nicht sicher, ob dies bei hohen Frequenzen etwas ungenauer ist als bei CTC, aber bei 3 Hz hat es perfekt funktioniert. Beachten Sie, dass 5208 der richtige OCR-Wert war, nicht 20 (erneut dank Gerben).
quelle
TCNT3=0;
im ISR () hinzugefügt und//TCCR3B |= (1 << WGM32);
im Setup () entfernt, wie Sie sagten. Ich habe auch versucht, diecont=0;
Zeile zu kommentieren, aber nichts hat sich geändertprintln(cont); delay(1000);
. Auch schließen Sie noch die Bits mit cli () und TCCR3A usw. richtig ein?