AVR学习笔记十二、AVR内部的看门狗操作实验
-------基于LT_Mini_M16
12.1 基于ATmega16内部看门狗操作实验
12.1.1、实例功能
AVR单片机的多数型号都有芯片内置的看门狗(watch dog)电路,看门狗电路实际上是一个定时器电路,该定时器采用独立的内部1M的RC振荡器驱动。
根据设置的看门狗定时时间,当程序运行时间超过定时时间后,如果没有及时复位看门狗(就是俗称的“喂狗”),看门狗定时器就会发生溢出,这个溢出将导致程序的复位,从而保证在程序跑飞的情况下,不会长时间没有响应。
本实例就利用WINAVR中自带的看门狗的操作函数来对ATmega16的内部看门狗进行操作。
本实例有两个功能模块:
● 了解WINAVR自带的看门狗操作函数。
● 编写程序,实现对ATmwga16内部口看门狗的操作。
通过本实例的学习,掌握以下知识点:
● 如何利用WINAVR自带的看门狗操作函数实现对ATmega16的内部看门狗的操作。
12.1.2 WINAVR中自带看门狗操作函数的说明
WINAVR中自带了看门狗操作函数,利用这些函数可以很轻松的实现对AVR单片机内部的看门狗进行控制。
如果要使用WINAVR中自带的看门狗操作函数,首先要在程序中包含看门狗操作函数的头文件,使用如下语句即可:
#include
下面我们来了解一下看门狗的操作常量的定义。
● 复位看门狗定时器。程序允许在使能看门狗定时器后,在溢出时间到达之前,调用该函数将看门狗复位。如果在规定时间内不调用此函数,则会发生看门狗溢出,导致程序复位。
#define wdt_reset() _asm_ _volatile_(“dwr”)
● 使能看门狗定时器,同时设置看门狗溢出时间
#define wdt_enable(timeout) _wdt_write((timeout) | _BV(WDE))
● 关闭看门狗定时器
#define wdt_disable() _wdt_write(0)
● 定义看门狗定时器溢出时间
#define WDTO_15MS 0
#define WDTO_30MS 1
#define WDTO_60MS 2
#define WDTO_120MS 3
#define WDTO_250MS 4
#define WDTO_500MS 5
#define WDTO_1S 6
#define WDTO_2S 7
12.1.3 电路和连接
本实例只是对AVR单片机内部看门狗定时器的操作。没有用到任何外部电路(当然电源电路、复位电路、下载电路等构成单片机工作的最基本电路还是需要的。^_^)。
12.1.4 程序设计
1、程序功能
程序的功能是对ATmega16单片机的内部看门狗定时器操作,通过控制8个LED显示看门狗是否及时复位,程序比较简单,直接看程序就能明白原理了。
2函数说明
本程序主要使用的是WINAVR自带的EEPROM读写函数,前面已经介绍过,在此不再说明。
3、使用WINAVR开发环境,使用的是外部12M的晶振,所以需要将makefile文件中的时钟频率修改为12M。另外在程序烧录到单片机的时候,熔丝位也要选择为外部12M晶振(注意是晶振,不是外部振荡器,一定不要选择错了,否则会导致单片机不能再烧写程序)。
4、程序代码
#include
#include
#include
//函数声明
void Delayus(unsigned int lus); //us延时函数
void Delayms(unsigned int lms); //ms延时函数
int main(void) //GCC中main文件必须为返回整形值的函数,没有参数
{
wdt_enable(WDTO_500MS); //启动看门狗,定时时间500MS
PORTB = 0x00; //熄灭所有LED
DDRB = 0xFF; //端口PortB设为输出口,通过LED的变化指示看门狗的复位
Delayms(100); //延时
PORTB = 0xff; //点亮所有LED
Delayms(100); //延时
//由于看门狗使用的是内部独立的1MRC振荡器,因此定时器的时间与电源电压、环境
//温度有关, //定时时间可能不准。
//在本实验中使用的是外部12M晶振,实验过程中发现,如果上面两个延时程序都改
//成延时200MS, //则即使在下面设置了喂狗程序,程序还是会复位,而改成延时100MS,//则程序不会复位。 //这可能是看门狗定时不准的例证。
while(1)
{
wdt_reset();
//喂狗,让程序正常运行,即LED一直点亮,注意一定要在while(1)中喂狗
//如果屏蔽这句话,则看门狗定时时间到后,会让程序复位,LED会不停的
//亮灭变化,
}
}
//us级别的延时函数
void Delayus(unsigned int lus)
{
while(lus--)
{
_delay_loop_2(3); //_delay_loop_2(1)是延时4个时钟周期,参数为3则延时12
//个时钟周期,本实验用12M晶体,则12个时钟周期为12/12=1us
}
}
//ms级别的延时函数
void Delayms(unsigned int lms)
{
while(lms--)
{
Delayus(1000); //延时1ms
}
}
//ms级别的延时函数
void Delayms(unsigned int lms)
{
while(lms--)
{
Delayus(1000); //延时1ms
}
}
本文来源:https://www.2haoxitong.net/k/doc/c10489eb6294dd88d0d26bd2.html
文档为doc格式