#include <avr/io.h>
#include <avr/interrupt.h>
uint16_t millis = 0;
void io_init() {
//se pone el puerto como salida.
DDRB = (1<<PB7);
//la salida se pone en 0 para que no interfiera con el oscilador.
PORTB = (0<<PB7);
}
//timer0 se utiliza para variar la intensidad del led, ahora se inicializa en baja intencidad y en el
//ISR se cambia a alta
void timer0_init () {
//contador en 0 para asegurar solo el primer ciclo, no tiene mucha importancia.
TCNT0 = 0;
//OCR0A en 0, para que la señal tenga un 100% de ciclo de trabajo.
OCR0A = 0;
//Se actvida el modo no invertido, al igual que el fast PWM.
TCCR0A = (2<<COM2A0) | (3<<WGM20);
//Se usara un preescalador para que la frecuencia no sea tan al para que no la diferencie el circuito
//ni tan baja para que el led se vea que se prende y apaga.
//pero para este caso funcionan todos los posibles.
TCCR0B = (5<<CS20);
}
//timer2 cuenta un milisegundo.
void timer2_init () {
//contador en 0 para asegurar solo el primer ciclo, no tiene mucha importancia.
TCNT2=0;
// (16,000,000 / 64) * 1 ms = 250, se pone el -1 por que al X + 1 ticks prende la bandera.
OCR2A = 250 - 1;
//Se activa el modo CTC, tambien en normal se puede.
TCCR2A = 2 << WGM20;
//Prescalador de 64 (0b011);
TCCR2B = 3 << CS20;
//Se deja pasar la interrupcion de comparacion para que salte a nuestro ISR de timer2 comp A.
TIMSK2 = 1 << OCIE2A;
//Se activan las interrupciones
sei();
}
//contar millis
ISR (TIMER2_COMPA_vect) {
//primero se aumenta millis cuando el contador activa la interrupcion
millis ++;
//si ya son 1000 millis, revisa que valor hay en OCRA (en que ciclo de trabajo esta, para cambiarlo)
if (millis>=1000) {
//Si tiene 0, entonces esta con un 100% de ciclo de trabajo, asi que lo cambia al otro ciclo que
//se busque.
if (OCR0A == 0) {
OCR0A=1;
}
//y en cualquier otro caso, lo pone a la intensidad mas alta.
else {
OCR0A = 0;
}
//se reinicia el contador de millis.
millis=0;
}
}
void main () {
//iniciamos gpio
io_init();
//iniciamos timer0
timer0_init();
//iniciamos timer2
timer2_init();
while (1);
}