¿La hoja de datos del AVR ATmega32 es incorrecta?

Actualmente estoy usando un ATmega32 para mantener el tiempo, así que leí cuidadosamente la hoja de datos y configuré el Temporizador 1 para generar una interrupción cada segundo.

De acuerdo con la siguiente fórmula en la hoja de datos, usando un reloj de 16 MHz, un preescalador de 256 y OCR1A = 31249, debería obtener una frecuencia de 1 Hz en modo CTC:

F O C norte A = F C yo k _ I / O 2 norte ( 1 + O C R norte A )

Esta fórmula está disponible en la página 99 de la hoja de datos de ATmega32 .

He configurado el temporizador 1 de la siguiente manera:

TCCR1A = 0;
TCCR1B = (1<<WGM12)|(1<<CS12);
OCR1A = 31249;
TIMSK = (1<<OCIE1A);

Aquí está el código de interrupción

ISR(TIMER1_COMPA_vect){
    sec++;
}

Luego, uso una pantalla LCD para imprimir continuamente el valor de sec y obtengo un tiempo de 0,5 segundos. En otras palabras, por cada segundo que pasa, el temporizador genera dos interrupciones.

Al principio pensé que tal vez me había equivocado en los fusibles, pero ese no parece ser el caso, ya que los retrasos funcionan bien. De todos modos, así es como configuré los fusibles:

-U lfuse:w:0xff:m -U hfuse:w:0x99:m

No tengo absolutamente ninguna idea de lo que está pasando, revisé todo dos veces, probé con otro ATmega32, probé con otro oscilador de cristal de 16 MHz y sigo obteniendo el mismo resultado.

¿La hoja de datos es incorrecta o me estoy perdiendo algo aquí?

TL;DR Respuesta: No. No, no lo es. ;-)

Respuestas (2)

Si el reloj del sistema es de 16 MHz y el preescalador es de 256 , el temporizador se ejecutará en dieciséis METRO H z 256 = 62500 H z , por lo que habrá un incremento en cada 1 62500 H z = dieciséis m s . Se generará una interrupción cuando el valor del contador sea 31249 . Si calculamos este tiempo: dieciséis m s × 31250 t i C k s = 0.5 s , que es exactamente el mismo resultado que tienes.

La ecuación en la hoja de datos tiene un propósito diferente:

Para generar una salida de forma de onda en C T C modo, el O C 1 A la salida se puede configurar para alternar su nivel lógico en cada coincidencia de comparación configurando los bits del modo de salida de comparación en modo alternar ( C O METRO 1 A 1 : 0 = 1 ) . El O C 1 A el valor no será visible en el pin del puerto a menos que la dirección de datos para el pin esté configurada como salida ( D D R O C 1 A = 1 ) . La forma de onda generada tendrá una frecuencia máxima de F O C 1 A = F C yo k I / O / 2 cuando O C R 1 A se pone a cero ( 0 X 0000 ) . La frecuencia de la forma de onda se define mediante la siguiente ecuación: (...)

Si midiera la frecuencia de un pin específico, creo que sería 1 Hz.


Para lograr un 1 s , dieciséis m s × 62500 = 1 s generación de interrupciones, necesita 62500 tics y, como el contador comienza desde 0, configure OCR1A en 31250 × 2 1 = 62499 , y dado que Timer1 es un temporizador de 16 bits, este valor no es demasiado alto (< 65535, 2 dieciséis 1 ).

En realidad es 62499, y necesitas sumar 1 antes de multiplicar por el período del reloj.
¡Oh! Me siento tan tonto en este momento, no me di cuenta de que cambió el pin, ¡así que asumí que era la misma fórmula! Entonces, si quiero exactamente 1 segundo (tan preciso como el cristal), debería usar OCR1A = 62499, ¿verdad? De acuerdo con la fórmula (ahora soltando el 2), eso debería darme exactamente 1 segundo.

Esa fórmula es para la frecuencia de salida del pin OCnA ("Para generar una salida de forma de onda en modo CTC, la salida OC1A se puede configurar para alternar su nivel lógico en cada coincidencia de comparación configurando los bits del modo de salida de comparación en modo alternar (COM1A1: 0 = 1). [...] La frecuencia de la forma de onda se define mediante la siguiente ecuación:"). Como está utilizando la interrupción, recibirá dos comparaciones por período. Elimina el 2 del denominador para calcular la frecuencia de interrupción.