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