Atmega328P Watch Dog Timer - Problema de retraso

Estoy tratando de dar un retraso de 0,5 segundos en el pin 13 del arduino usando la interrupción del temporizador Watch Dog, el código cumple y funciona bien, pero el LED parpadea tan rápido que parece que parpadea con un retraso de 50 ms, no con un retraso. de 0,5 segundo. Por favor ayuda. Gracias de antemano.

#define F_CPU 16000000UL
#include<avr/io.h>
#include<avr/interrupt.h>
#include<avr/wdt.h>

int main(void)
{
  cli();
  wdt_reset();

  WDTCSR |=(1<<WDP2) | (1<<WDP0);

  WDTCSR |= (1<<WDIE);
  WDTCSR |= (1<<WDE);

  sei();

  DDRB |= 0b00100000;

  PORTB |= 0b00000000;

  while(1)
  {

  }
}

ISR(WDT_vect) {

 PORTB ^= 0b00100000;

}
Intente configurar WDE en 0 en lugar de 1; eso debería generarle una interrupción de 500 ms sin reinicio del sistema. Con ese código, esperaría que el sistema se reinicie cada 500 ms inmediatamente después de ingresar al ISR, y dado que no borra el indicador de interrupción, ingresa ese ISR inmediatamente cuando configura WDIE después del reinicio, alternando el pin.
Probado, sigue siendo el mismo problema. está parpadeando tan rápido.
¿Está seguro de que simplemente no necesita borrar la interrupción en el ISR?
La hoja de datos dice "las alteraciones a la configuración del Watchdog deben seguir secuencias cronometradas" con el "bit de habilitación del cambio del Watchdog (WDCE)" y también tiene un código de ejemplo. ¿Por qué no usas eso?

Respuestas (1)

Si leí la hoja de datos (p. 54-55) correctamente, debe configurar el WDCEbit WDTCSRpara poder cambiar el prescaler. La configuración predeterminada para los bits del preescalador es 000de aproximadamente 16 ms de retraso.

Además, si configura ambos WDEy WDIE, el perro guardián funciona en "Modo de interrupción y reinicio del sistema", donde el primer tiempo de espera de WD activa la interrupción y el segundo reinicia el dispositivo, a menos que el WDIEbit se establezca nuevamente después de la interrupción. O si solo desea la interrupción, no el restablecimiento, simplemente déjelo WDEsin configurar.

Entonces, parafraseando el código de ejemplo, creo que querrás algo como esto:

cli();
WDTCSR |= (1<<WDCE);  /* enable change */
WDTCSR = (1<<WDIE) | (1<<WDP2) | (1<<WDP0);  /* enable interrupt and set prescaler */
sei();