watchdog в Atmega8

Тема в разделе "Микроконтроллеры AVR", создана пользователем DrProg, 17 ноя 2015.

  1. DrProg

    DrProg Вечный нерд

    Что то я заблудился в трех соснах. Тестовая задача: включить вачдог на Атмеге8 с максимальным периодом 2.2 сек и проверить как оно работает. Желательно без библиотеки, напрямую, так сказать.
    Сначала запуск программы с быстрым миганием, потом медленное мигание со сбросом вачдога, потом бесконечный цикл в котором вачдог наконец должен сработать и резетить МК. Код:

    Код (C++):
    // сброс вачдога
    #define wdt_reset() \
      __asm__ __volatile__ ("wdr")


    void setup() {
      WDT_off();
      pinMode(13, OUTPUT);  // быстро мигаем при запуске
      for (int i = 0; i < 20; i++) {
        digitalWrite(13, !digitalRead(13));
        delay(20);
      }
      WDT_on();       // вкл вачдог
    }

    void loop() {
      for (int i = 0; i < 20; i++) {  // мигаем медленно со сбросом вачдога
        digitalWrite(13, !digitalRead(13));
        wdt_reset();
        delay(200);
      }
      while (true);      // зависаем (через 2.2 сек должен быть резет)
    }


    inline void WDT_on(void) {   // запуск вачдога с периодом 2.2с
      WDTCR = 0b00001111;
    //  WDTCR = 0x00;
    //  WDTCR |= ((1 << WDE) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0));
    }

    inline void WDT_off(void) {  // выкл вачдога
      wdt_reset();
      WDTCR |= (1 << WDCE) | (1 << WDE);
      WDTCR = 0x00;
    }
    На деле же после быстрого мигания МК сразу резетится не выждав ни фазы медленного мигания ни даже обещанных 2.2 сек. То есть он запускается, но как будь то с гораздо меньшим периодом или запускается не так. В чем причина?
     
    Последнее редактирование: 17 ноя 2015
    ИгорьК нравится это.
  2. DrProg

    DrProg Вечный нерд

    Все, разобрался сам. Оказывается бит WDCE надо подпинывать не только при выключении собаки, но и при включении. Если кому интересно, то готовый код выглядит так:
    Код (C++):
    // сброс вачдога
    #define wdt_reset() \
      __asm__ __volatile__ ("wdr")


    void setup() {
      WDT_off();      // выкл вачдог
      pinMode(13, OUTPUT);  // быстро мигаем при запуске
      for (int i = 0; i < 20; i++) {
        digitalWrite(13, !digitalRead(13));
        delay(50);
      }
      WDT_on();       // вкл вачдог
    }

    void loop() {
      for (int i = 0; i < 20; i++) {  // мигаем медленно со сбросом вачдога
        digitalWrite(13, !digitalRead(13));
        wdt_reset();
        delay(250);
      }
      while (true);      // зависаем (через 2.2 сек должен быть резет)
    }


    inline void WDT_on(void) {   // запуск вачдога с периодом 2.2с
      WDTCR = 0x1F;
      WDTCR |= (1 << WDE) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0);
    //  то же самое побитно:
    //  WDTCR = 0b00011111;
    //  WDTCR = 0b00001111;
    }

    inline void WDT_off(void) {  // выкл вачдога
      wdt_reset();
      WDTCR |= (1 << WDCE) | (1 << WDE);
      WDTCR = 0x00;
    // побитно:
    // WDTCR = 0b00011000;
    // WDTCR = 0b00000000;
    }
     
    Последнее редактирование: 17 ноя 2015
    ИгорьК, Radius и Tomasina нравится это.
  3. DrProg

    DrProg Вечный нерд

    Еще возник вот такой нестандартный вопрос: разумно ли сделать сброс ватчдога через прерывание по таймеру? Иными словами, в случае если МК зависает зависают ли таймеры или эти процессы никак не связаны и вачдог будет исправно сбрасываться на зависшем МК?
     
    ИгорьК нравится это.
  4. ИгорьК

    ИгорьК Гуру

    Интересный вопрос. Полагаю, сбрасывать собаку в прерывании не имеет смысла. Собака охраняет "весь дом".
    Но ничто не мешает поэкспериментировать. Сделайте в теле программы какую-нибудь безумную задержку, или, например, запись в массив с выходом за границы с задержкой и миганием диодом после записи каждого элемента, а собаку - в прервыание, и посмотрите что получится.
     
  5. Tomasina

    Tomasina Сушитель лампочек Модератор

  6. AlexU

    AlexU Гуру

    IMHO -- не разумно, хотя можно убедить в обратном.
    У watchdog'а свой таймер с прерыванием, зачем лепить еще один?