VideoHelp Forum

Our website is made possible by displaying online advertisements to our visitors. Consider supporting us by disable your adblocker or Try ConvertXtoDVD and convert all your movies to DVD. Free trial ! :)
+ Reply to Thread
Results 1 to 2 of 2
Thread
  1. 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:
    Quote Quote  
  2. 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);
    }
    to this:

    Code:
    if (state == 0) {
        WDTCSR = (1 << WDCE) | (1 << WDE);
        WDTCSR = 0;
    } else {
        WDTCSR = (1 << WDCE) | (1 << WDE);
        WDTCSR = (1<<WDP3) | (1<<WDP0) | (1<<WDIE);
    }
    You also need to set watchdog_counter back to zero after led_blink() in main().

    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.
    Quote Quote  



Similar Threads