I have AVR Atmega328p which I want to blink for 5 secs every 16 secs (to test the watchdog interrupts).
Then how to bootloader atmega328p
I have the following code, which keeps restarting, and the last line is:
test_blink(2);
Which I know because the led on PC2 is always on. Where did I wrong? I re-checked the WD settings for 10s times already..
#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++;
}
}
I am using the following fuses, and avrdude command:
avrdude -B 250 -c usbtiny -P usb -p m328p -U lfuse:w:0xD3:m -U hfuse:w:0xDF:m -U efuse:w:0x07:
Try StreamFab Downloader and download from Netflix, Amazon, Youtube! Or Try DVDFab and copy Blu-rays!
+ Reply to Thread
Results 1 to 2 of 2
Thread
-
-
I ran your code with the clock set to the internal 128KHz clock (via the fuses). I verified the CPU was running at 128 KHz. But I was seeing WD interrupts every 30 ms (by pulsing an output pin within the ISR and watching it with a scope). The problem is too much time is passing between writing the WD prescale enable bits and writing to the prescale bits. Change this:
Code:WDTCSR = (1 << WDCE) | (1 << WDE); if (state == 0) { WDTCSR = 0; } else { WDTCSR = (1<<WDP3) | (1<<WDP0) | (1<<WDIE); }
Code:if (state == 0) { WDTCSR = (1 << WDCE) | (1 << WDE); WDTCSR = 0; } else { WDTCSR = (1 << WDCE) | (1 << WDE); WDTCSR = (1<<WDP3) | (1<<WDP0) | (1<<WDIE); }
The timing may still be not quite right. I'm seeing the LED on for 5 seconds off for about 9. I'm sure you can track that down yourself.
Some other issues:
That reset_pins() is really nasty. I would initialize the pins at startup and turn individual pins off/on as necessary.
I wouldn't call a slow function like test_blink() (twice!) within an ISR.Last edited by jagabo; 23rd Jun 2017 at 23:29.
Similar Threads
-
flv restarting
By gmanm1 in forum Media Center PC / MediaCentersReplies: 6Last Post: 24th Jan 2014, 09:18