今天测试了下看门狗。
可以使用wdt.h中的wdt_enable(value)和wdt_disable(),也可以使用自己定义的WDT_enable(uint8_t count)和WDT_disable(void)。
复位看门狗用wdt.h中的wdt_reset()。
----------------------------------------------------------------------------------------------------------------------------------
1、上电时PA0输出0.5s的高电平(示波器)
2、接着PA0拉低,同时启用看门狗(2s后复位)
3、如果看门狗复位,那么复位后会再次将PA0会被拉高,而且复位前PA0的低电平持续时间应该是2s(5V电源下)
#include <avr/io.h> #include "watch_dog.h" #include "_noinit.h" #include "system.h" #include "config.h" int main(void) { // PA0为输出口 DDRA = (IO_OUTPUT << DDA0); // PA0拉高 PORTA = (1 << PA0); // 维持0.5秒 delay_ms(500); // PA0拉低 PORTA &= ~(1 << PA0); // 使能看门狗 @ 2s wdt_enable(WDTO_2S); // WDT_enable(WDTO_2S); // // 1. 看门狗在2秒后复位,所以PA0的低电平会维持2秒 // 2. 而后芯片复位,PA0会被拉高 // 3. 跳转到1 // // 记录复位次数 _noinit_using(); while(1) { } return 0; }
上面的_noinit_using()使用了.noinit特性,通过观察PORTB上的8位LED的状态(二进制计数器)得知复位次数。
uint8_t v_noinit __attribute__ ((section(".noinit"))); void _noinit_using(void) { v_noinit++; // 8位LED,低推 DDRB = 0xFF; PORTB = 0xFF; PORTB = v_noinit; }_noinit_using具体原理参考这里:
http://blog.csdn.net/manon_des_source/article/details/51536802
1、示波器可以看到PA0输出的是0.5的高电平H和1.86秒的低电平L。
同时PORTB上的8位LED组成的二进制计数器在0.5秒的高电平出现时就会加1。
2、0.5秒高电平是启动看门狗之前的时间,1.86秒是看门狗定时器溢出时间,溢出后复位MCU。
于是又重新出现0.5秒的高电平。
这说明看门狗工作正常,确实实现了复位MCU。
3、当然每次下载程序或看门狗复位后,PORTB上的8位LED组成的二进制计数器也会加1
----------------------------------------------------------------------------------------------------------------------------------
1、复位时间只有1.86s,而不是2秒。
测试电源电压是5V,所以应该是温度和示波器造成的误差。
特地查看了下Atmega16的Datasheet,发现在室温30度下,WDT的频率大概是1020Hz(下图)。
频率是1.02倍,对应的时间应该是 2s / (1020 / 1000) = 1.96s。
剩下的误差,也许是示波器的问题吧。
另外、芯片使用的是8MHz的时钟,这需要手动校准,看看复位时间是否更接近2s
或者使用内部自动校准的1MHz时钟测试。
----------------------------------------------------------------------------------------------------------------------------------
http://download.csdn.net/detail/manon_des_source/9557733