atmega328p El perro guardián sigue reiniciando

0

Tengo AVR Atmega328p que quiero parpadear durante 5 segundos cada 16 segundos (para probar las interrupciones de vigilancia).

Tengo el siguiente código, que sigue reiniciando, y la última línea es:

test_blink(2);

Lo sé porque el led en PC2 siempre está encendido. Donde me equivoque Volví a revisar la configuración de WD 10s veces ya.

#define F_CPU 128000

// LED Definitions
#define LED_PORT PORTD
#define LED_PIN PD6
#define LED_DDR DDRD
#define LED_PWM_PCNT 50

// Watchdog definitions
// counter = 2*8 = 16 seconds
#define WD_COUNTER_MAX 2

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <stdint.h>
#include <util/delay.h>
#include <avr/wdt.h>

// Global watchdog counter (for wake-up counts)
volatile uint8_t watchdog_counter;

// Function declarations [may split to files]
void reset_pins();
void led_blink();
void sleep_me();
void setup_init();
void test_blink(int pin);
void setup_watchdog(uint8_t state);

void led_blink()
{
    LED_DDR = (1<<LED_PIN);
    LED_PORT = (1<<LED_PIN);
    _delay_ms(5000);
}

void test_blink(int pin)
{
    reset_pins();
    DDRC |= (1<<pin);
    PORTC |= (1<<pin);
    _delay_ms(300);
    reset_pins();
}

void reset_pins()
{
    DDRB = 0;
    DDRC = 0;
    DDRD = 0;
    PORTB = 0;
    PORTC = 0;
    PORTD = 0;
}

void setup_watchdog(uint8_t state)
{
    // Watchdog:
    // Clear WD reset flag
    MCUSR = 0;

    WDTCSR = (1 << WDCE) | (1 << WDE);
    if (state == 0) {
        WDTCSR = 0;
    } else {
        WDTCSR = (1<<WDP3) | (1<<WDP0) | (1<<WDIE);
    }
    wdt_reset();
    test_blink(2);
}

void sleep_me()
{
    ADCSRA = 0;
    reset_pins();
    PRR = 0xff;

    // Set sleep mode to POWER DOWN
    SMCR |= (1 << SM1);
    // Enable SLEEP
    SMCR |= (1<<SE);

    // Enable global interrupts.
    sei();

    // Disable pull-up resistors
    SMCR |= (1<<PUD);

    test_blink(2);
    setup_watchdog(1);
  sleep_cpu();
}

void setup_init()
{
    watchdog_counter = 0;
    setup_watchdog(1);
}

// watchdog interrupt
ISR(WDT_vect) {
    setup_watchdog(0);
}

int main(void)
{
    cli();
    setup_init();
    test_blink(4);
  while(1)
  {
        cli();
        // Disable SLEEP
        SMCR &= ~(1<<SE);

        if (watchdog_counter >= WD_COUNTER_MAX) led_blink();
        else sleep_me();

        watchdog_counter++;
  }
}

Estoy usando los siguientes fusibles y el comando avrdude:

avrdude -B 250 -c usbtiny -P usb -p m328p -U lfuse:w:0xD3:m -U hfuse:w:0xDF:m -U efuse:w:0x07:m -U flash:w:watchdog.hex:a
    
pregunta gabi

1 respuesta

1

Por lo que puedo ver, no está habilitando interrupciones globales en el registro de estado.

De la hoja de datos:

  

Bit 6 - WDIE: habilitación de interrupción de vigilancia   Cuando este bit se escribe en '1' y se establece el bit I en el registro de estado, se habilita la interrupción de vigilancia.   Si WDE se borra en combinación con esta configuración, el temporizador de vigilancia está en modo de interrupción y el   la interrupción correspondiente se ejecuta si se produce un tiempo de espera en el temporizador de vigilancia. Si se configura WDE, el Watchdog   El temporizador está en modo de interrupción y reinicio del sistema. El primer tiempo de espera en el temporizador de vigilancia establecerá WDIF.   La ejecución del vector de interrupción correspondiente borrará WDIE y WDIF automáticamente por hardware (el   El perro guardián pasa al modo de reinicio del sistema)

Busque en la hoja de datos "SREG" y vea el bit 7-I. Este bit debe establecerse para que las interrupciones funcionen correctamente.

    
respondido por el pfl

Lea otras preguntas en las etiquetas