ATtiny88初體驗(四):看門狗

2023-08-25 18:01:28

ATtiny88初體驗(四):看門狗

ATtiny88微控制器的看門狗使用內部獨立的128KHz時鐘源,擁有3種工作模式:

  • Interrupt模式:超時產生中斷;
  • System Reset模式:超時產生系統復位;
  • Interrupt & System Reset模式:超時產生中斷,中斷處理完成後產生系統復位。

當熔絲位 WDTON 被程式設計時(值為0),將強制將看門狗設為System Reset模式,此時 WDEWDIE 位將被鎖定為 10

清除 WDE 位和修改 WDP 需要按照下面的順序進行操作:

  1. WDCEWDE 位寫1,不管 WDE 位先前是什麼值,都必須寫1。
  2. 在接下來的4個時鐘裡,修改 WDEWDP 位,清除 WDCE 位,這些必須在一次操作內完成。

注意:

  1. 為了防止程式陷入復位迴圈,不管有沒有用到看門狗,在初始化時,都建議清除 WDRF 標誌位和 WDE 位。
  2. 在任何對 WDP 位的修改之前,建議都復位看門狗,否則可能會導致意外的復位。

暫存器

  • WDRF :看門狗系統復位標誌位。
  • BORF :欠壓復位標誌位。
  • EXTRF :外部復位標誌位。
  • PORF :上電覆位標誌位。

  • WDIF :看門狗中斷標誌位。
  • WDIE :看門狗中斷使能。
  • WDCE :看門狗修改使能,只有設定此位,才能修改 WDEWDP 位。
  • WDE :看門狗系統復位使能。
  • WDP[3:0] :看門狗定時器分頻。

程式碼

程式碼的檔案結構如下:

.
├── Makefile
├── inc
│   ├── serial.h
│   └── serial_stdio.h
└── src
    ├── main.c
    ├── serial.c
    └── serial_stdio.c

其中, src/main.c 的內容如下:

#include <stdint.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <serial_stdio.h>

static void watchdog_setup(void);

int main(void)
{
    cli();
    DDRD = _BV(DDD0);                   // set PD0 as output
    stdio_setup();                      // initialize stdio
    sei();

    if (MCUSR & _BV(WDRF)) {            // check if watchdog reset
        printf("Watchdog Reset.\r\n");
    }
    if (MCUSR & _BV(BORF)) {            // check if brown-out reset
        printf("Brown-out Reset.\r\n");
    }
    if (MCUSR & _BV(EXTRF)) {           // check if external reset
        printf("External Reset.\r\n");
    }
    if (MCUSR & _BV(PORF)) {            // check if power-on reset
        printf("Power-on Reset.\r\n");
    }
    MCUSR = 0;                          // clear reset flags

    watchdog_setup();                   // initialize watchdog as timer

    for (;;);
}

static void watchdog_setup(void)
{
    cli();
    wdt_reset();                        // reset watchdog counter
    MCUSR &= ~_BV(WDRF);                // clear watchdog reset flag
    WDTCSR = _BV(WDCE) | _BV(WDE);      // enable watchdog change
    WDTCSR = _BV(WDIE) | _BV(WDP2) | _BV(WDP0); // interrupt mode, 0.5s
    sei();
}

ISR(WDT_vect)
{
    uint8_t sreg = SREG;
    PIND = _BV(PIND0);                  // toggle PD0
    SREG = sreg;
}

上述程式碼將看門狗設定為定時器中斷模式,定時週期為0.5s,在中斷程式裡,翻轉PD0的輸出狀態。

參考資料

  1. ATtiny88 Datasheet