今天测试了下看门狗。
可以使用wdt.h中的wdt_enable(value)和wdt_disable(),也可以使用自己定义的WDT_enable(uint8_t count)和WDT_disable(void)。
复位看门狗用wdt.h中的wdt_reset()。
----------------------------------------------------------------------------------------------------------------------------------
使用PA0测试复位时间:
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特性测试复位:
上面的_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.youkuaiyun.com/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
|<----待测试-question-001
或者使用内部自动校准的1MHz时钟测试。
----------------------------------------------------------------------------------------------------------------------------------
完整代码:
http://download.youkuaiyun.com/detail/manon_des_source/9557733