ATtiny88初体验(四):看门狗
ATtiny88单片机的看门狗使用内部独立的128KHz时钟源,拥有3种工作模式:
- Interrupt模式:超时产生中断;
- System Reset模式:超时产生系统复位;
- Interrupt & System Reset模式:超时产生中断,中断处理完成后产生系统复位。
当熔丝位 WDTON
被编程时(值为0),将强制将看门狗设为System Reset模式,此时 WDE
和 WDIE
位将被锁定为 1
和 0
。
清除 WDE
位和修改 WDP
需要按照下面的顺序进行操作:
- 向
WDCE
和WDE
位写1,不管WDE
位先前是什么值,都必须写1。 - 在接下来的4个时钟里,修改
WDE
和WDP
位,清除WDCE
位,这些必须在一次操作内完成。
注意:
- 为了防止程序陷入复位循环,不管有没有用到看门狗,在初始化时,都建议清除
WDRF
标志位和WDE
位。 - 在任何对
WDP
位的修改之前,建议都复位看门狗,否则可能会导致意外的复位。
寄存器
WDRF
:看门狗系统复位标志位。BORF
:欠压复位标志位。EXTRF
:外部复位标志位。PORF
:上电复位标志位。
WDIF
:看门狗中断标志位。WDIE
:看门狗中断使能。WDCE
:看门狗修改使能,只有设置此位,才能修改WDE
和WDP
位。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的输出状态。