11.1 看门狗定时器的设置例程
例11.1设置看门狗定时器处于看门狗状态,当定时时间到时,看门狗复位单片机系统,从而使LED闪烁。
#include<msp430.h>
void main(void)
{
unsigned int i=0;
WDTCTL=WDTPW+WDTHOLD; //关闭看门狗
P1DIR|=BIT0; //设置P1.0为输出方向
P1OUT&=~BIT0; //熄灭P1.0外接的红色LED
for(i=0;i<50000;i++); //软件延时
P1OUT|=BIT0; //点亮P1.0外接的红色LED
WDTCTL=WDT_ARST_250; //设置看门狗为每250ms复位一次。若去掉该句,则红色LED会常亮
}
上述程序中,若没有看门狗定时地复位系统,LED是常亮的。正是看门狗每250ms复位一次系统,使上述程序被反复执行,从而使LED闪烁。查看msp430g2553.h头文件可知,上述程序中WDT_ARST_250的宏定义为WDTPW+WDTCNTCL+WDTSSEL+WDTIS0,其中WDTPW为看门狗定时器的密码,是操作看门狗控制寄存器WDTCTL必须的,如果没有该密码,将复位单片机;WDTCNTCL为看门狗计数器清零,即让看门狗定时器从零开始计数;WDTSSEL给看门狗定时器选择时钟源为ACLK,且ACLK的默认值为32768Hz;WDTIS0设定看门狗定时器的计数值为8192,则其定时时间为8192/32768=0.25s=250ms;而且WDTPW、WDTCNTCL、WDTSSEL、WDTIS0在头文件中都有相应的宏定义。在WDT_ARST_250的宏定义中没有关于WDTTMSEL位的设置,且其缺省值为0,则看门狗定时器处于看门狗模式。
例11.2 简单的“喂狗”程序。
在例11.1程序的基础上,加入喂狗环节,在看门狗定时时间到之前,看门狗定时器被清零并重新计时,则看门狗定时器不再复位系统,LED不再闪烁,变为常亮。
#include<msp430.h>
void main(void)
{
unsigned int i=0;
WDTCTL=WDTPW+WDTHOLD; //关闭看门狗
P1DIR|=BIT0;//设置P1.0为输出方向
P1OUT&=~BIT0; //熄灭P1.0外接的红色LED
for(i=0;i<50000;i++); //软件延时
P1OUT|=BIT0; //点亮P1.0外接的红色LED
WDTCTL=WDT_ARST_250; //设置看门狗为每250ms复位一次
while(1)
{
for(i=0;i<1000;i++); //这个软件延时不能超过250ms,否则看门狗就复位了。
//若将i<1000改为i<10000,看门狗会产生复位,红色LED闪烁。
WDTCTL=WDT_ARST_250; //在定时时间250ms到达之前再次设定定时间隔,并清零看门狗定时
//器,使其从零开始重新计时,此即俗称的“喂狗”。由于及时的“喂狗”,
} //则看门狗定时器不会产生复位动作。
}
例11.3 将看门狗作为定时器来使用,当定时时间到时产生中断,在中断服务程序中让外接于P1.0的红色LED闪烁。
#include<msp430.h>
void main(void)
{
WDTCTL=WDT_ADLY_1000; //设定看门狗为定时器模式,定时时间为1000ms
IE1|=WDTIE; //使能看门狗中断
P1DIR|=BIT0; //设置P1.0为输出方向
_EINT(); //使能总中断
}
//==========看门狗中断服务程序===============
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
P1OUT^=BIT0; //让外接于P1.0的红色LED闪烁
IFG1&=~WDTIFG; //当中断被服务后,WDTIFG标志会被自动清除,也可以用软件清除
}
查看msp430g2553.h头文件可知,上述程序中的WDT_ADLY_1000被宏定义为WDTPW+ WDTTMSEL+WDTCNTCL+WDTSSEL。其中WDTPW为看门狗定时器的密码;WDTTMSEL选择看门狗为间隔定时器模式;WDTCNTCL清零看门狗计数器;WDTSSEL给看门狗定时器选择时钟源为ACLK,且ACLK的默认值为32768Hz;WDTISx位没有置位,即选择其默认值00,则看门狗定时器的计数值为32768,其定时时间为32768/32768=1s=1000ms。另需注意:如果LaunchPad开发板上没有外接32768Hz的晶振,则脱离仿真后不能正常运行(闪烁间隔特别长),因为WDT_ADLY_1000设定为使用了32768Hz的晶振。
例11.4 NMI中断,将RST/NMI管脚设为NMI模式,当RST复位按键被按下时,引起NMI中断(Non-Maskable Interrupt,不可屏蔽中断),在NMI中断服务程序中取反红色LED灯的状态。
#include<msp430.h>
void main(void)
{
WDTCTL=WDTPW+WDTHOLD+WDTNMI+WDTNMIES; //关闭看门狗,并且设置RST/NMI管脚为NMI模式,
//且下降沿产生NMI
IE1|=NMIIE; //NMI中断使能,因NMI为不可屏蔽中断,因此无需开总中断使能
P1DIR|=BIT0;
P1OUT|=BIT0; //点亮外接于P1.0的红色LED
LPM3; //进入低功耗3模式
}
//==========NMI中断服务程序===============
#pragma vector=NMI_VECTOR
__interrupt void NMI_ISR(void)
{
P1OUT^=BIT0; //P1.0的状态取反,使外接于P1.0的红色LED闪烁
IFG1&=~NMIIFG; //清除NMI的中断标志
IE1|=NMIIE; //NMI中断使能,因NMI为不可屏蔽中断,因此无需开总中断使能
//NMI中断被执行后,其中断使能位会被自动清除,若要再次进入
//中断,必须重新使能NMI中断。
}
注:上述中断服务程序中没有包括按键去抖部分。
例11.5 用PWM波来点亮与P1.6相连接的绿色LED
/**********************************
* 用WDT产生定时中断,在WDT中断服务程中让全局
* 变量a加1,在while(1)主循环中,根据a的值
* 切换TACCR1的值,从而改变了PWM波的占空比,
* 则绿色LED的亮度自动随之改变。
**********************************/
#include"msp430g2553.h"
int a=0;
void main()
{
BCSCTL3|=LFXT1S_2; //选择VLO为低频时钟
WDTCTL=WDT_ADLY_250;//用看门狗产生定时中断,为了便于观察LED灯的亮度变化,选择ACLK
IE1|=WDTIE; //WDT定时模式下的中断允许。
P1DIR|=BIT6+BIT0;
P1SEL2&=~BIT6;
P1SEL|=BIT6; //选择P1.6的第二输出功能,即输出PWM波
_EINT();
TACTL|= MC_1+TASSEL_2+ID_0; //设置TA增量计数至TACCR0,选择SMCLK,不分频
TACCTL1=OUTMOD_7; //PWM输出方式7:PWM复位、置位方式
TACCR0=328-1; //为TACCR0赋初值
TACCR1=0; //为TACCR1赋初值;本句可以不要。
while(1)
{
switch(a) //用switch()语句来进行判断和切换
{
case 0: TACCR1=0; //TACCR1值的大小决定了PWM波的占空比,占空比越大,LED灯越亮。
P1OUT&=~BIT0; //熄灭红色LED
break;
case 1: TACCR1=1;
break;
case 2: TACCR1=5;
break;
case 3: TACCR1=12;
break;
case 4: TACCR1=20;
break;
case 5: TACCR1=50;
break;
case 6: TACCR1=80;
break;
case 7: TACCR1=110;
break;
case 8: TACCR1=150;
break;
case 9: TACCR1=200;
break;
case 10:TACCR1=260;
break;
case 11:TACCR1=328;
P1OUT|=BIT0;//点亮红色LED
break;
default:
break;
}
}
}
#pragma vector=WDT_VECTOR
__interrupt void Watchdog_ISR(void)
{
IFG1&=~WDTIFG;
a++; //在看门狗中断中改变a的值
if(a==12)
a=0;
}