Estoy jugando con el TIMER0 de ATMEGA168A. La CPU está funcionando a 20MHz y hay dos tratamientos.
a) Parpadea un LED a una frecuencia de 20 ms utilizando un precalculador 1024. En ese caso, cuento las veces que se produce un desbordamiento para la frecuencia que el prescaler de 1024 'me da'. Y de acuerdo con la fórmula, para lograr un retraso de 20 ms con 1024 preescalador, el temporizador debe desbordarse 1 vez y en el segundo bucle para contar 145 "tics" más. Con ese método, el LED parpadea pero, por supuesto, no podemos verlo. Aquí está el código:
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile uint8_t total_overflow;
void timer0_init(void)
{
// Setting the 1024 prescaler
TCCR0B |= (1 << CS00) | (1 << CS02);
// Initialize Timer0
TCNT0 = 0;
// Initialize the overflow interrupt for TIMER0
TIMSK0 |= (1 << TOIE0);
// Enable global interrupts
sei();
// Initialize total_overflow variable
total_overflow =0;
}
// Interrupt service routine
ISR(TIMER0_OVF_vect)
{
total_overflow++;
}
int main(void){
DDRB = 0b00000001; // SET PB0 pin as output
timer0_init();
while(1)
{
if(total_overflow >= 1)
{
if(TCNT0 >= 145){
PORTB ^= (1 << 0);
TCNT0 = 0;
total_overflow = 0;
}
}
}
}
b) Parpadea un LED a una frecuencia de 20 ms pero sin usar ningún prescaler. CPU y esta vez corre a 20MHz. Aquí ocurre que para lograr un retardo de tiempo de 20 ms, TIMER0 debe desbordarse 1568 veces y en la 1569a vez para contar 160 'tics' más. En ese caso el LED no se enciende. Aquí está el código:
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile uint8_t total_overflow;
void timer0_init(void)
{
// Setting the no prescaler
TCCR0B |= (1 << CS00);
// Initialize Timer0
TCNT0 = 0;
// Initialize the overflow interrupt for TIMER0
TIMSK0 |= (1 << TOIE0);
// Enable global interrupts
sei();
// Initialize total_overflow variable
total_overflow =0;
}
// Interrupt service routine
ISR(TIMER0_OVF_vect)
{
total_overflow++;
}
int main(void){
DDRB = 0b00000001; // SET PB0 pin as output
timer0_init();
while(1)
{
if(total_overflow >= 1568)
{
if(TCNT0 >= 160){
PORTB ^= (1 << 0);
TCNT0 = 0;
total_overflow = 0;
}
}
}
}
¿Alguna idea de por qué sucede esto? ¿Estoy haciendo algo mal o hay una limitación de cuántas veces se puede desbordar un temporizador (< - eso parece una idea tonta).
Gracias.