Estoy tratando de verificar la frecuencia de Timer3 usando un contador. El valor del contador, declarado como volátil, se incrementa en el ISR y cada segundo la suma se muestra en el bucle principal y el valor se restablece a cero.
El temporizador se ha configurado correctamente. (Si elijo un temporizador de 3Hz, puedo ver el led parpadeando)
El problema
El contador no se incrementa. Aquí está la salida:
Setup Completed
tick: 1
tick: 0
tick: 0
tick: 0
CÓDIGO
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++;
}
EDITAR Este temporizador se usa para leer un valor anlog de un acelerómetro y almacenarlo en una matriz de flotante. Pero en este momento estoy atascado en este problema de actualización.
SOLUCIÓN 1 Gracias a 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++;
}
SOLUCIÓN 2 Gracias a 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
línea, ve que el LED parpadea aproximadamente una vez por segundo (cada 0.66s)?digitalWrite
y configuroOCR3B = 5;
el led parpadea aproximadamente a esa frecuencia.cont = 0;
interior del bucle? ¿Qué pasa entonces?Respuestas:
En modo CTC, la parte superior es
OCR3A
,OCR3B
¡ no !Después de eso
TIMSK3 |= (1 << OCIE3B);
también se debe cambiar aTIMSK3 |= (1 << OCIE3A);
, yISR(TIMER3_COMPB_vect)
aISR(TIMER3_COMPA_vect)
Para 3Hz,
OCR3A
debe ser 5208, no 20.Técnicamente
TCCR3B |= (1 << WGM12);
debería serTCCR3B |= (1 << WGM32);
fuente
TIMSK3 |= (1 << OCIE3B);
. Gracias Gerben! Modifique su respuesta y la aceptaré como solución.ISR(TIMER3_COMPB_vect)
debería serISR(TIMER3_COMPA_vect)
. Si no se define un ISR, el AVR se reiniciará, como lo estaba experimentando. Me alegra que lo hayas hecho funcionar.Parece que mi respuesta a esta pregunta estaba incompleta anteriormente, gracias por señalar que el modo CTC solo funciona con OCR3A Gerben. Pido disculpas por no probar una respuesta antes de publicarla.
Dada la información solo en esta pregunta, la respuesta de Gerben está completa, pero dado que su otra pregunta implica que no puede usar OCR3A debido a la biblioteca Servo, agregaré un poco. (También he editado esa respuesta)
puede emular el comportamiento del modo CTC configurando TCNT3 en 0 en su rutina de interrupción. Recuerde eliminar la línea que activa el modo CTC en su código.
He probado tu código con este ISR:
y esta configuración de los registros del temporizador
Esto podría ser un poco menos preciso a altas frecuencias que CTC, no estoy seguro, pero a 3Hz funcionó perfectamente. Tenga en cuenta que 5208 era el valor de OCR correcto, no 20 (nuevamente gracias a Gerben).
fuente
TCNT3=0;
en el ISR () y eliminé//TCCR3B |= (1 << WGM32);
en la configuración () como dijiste. También he intentado comentar lacont=0;
línea pero nada ha cambiadoprintln(cont); delay(1000);
. También todavía incluye los bits con cli () y TCCR3A, etc. ¿correcto?