1、首先知道看门狗有三种工作方式:
①不工作
②当中断计数器
③看门狗
2、熟悉和看门狗的三个寄存器:
看门狗控制,对应的中断使能和中断标志。
看门狗控制
中断使能:
中断标志:
注:寄存器的每个位的说明不做解释,可以网上查找
3、熟悉寄存器之后,分别讲下三种状态怎么设置:
①不工作模式
就是关闭看门狗,因为看门狗时默认打开状态的,所以,如果不想用这个功能必须要先设置一下:
先写出需要控制的寄存器:WDTCTL;把需要需要改变的值赋值到这个寄存器中,这里因为寄存器的每个位在头文件之中都有自己明确的定义(define),所以可以简写成以下模式:
WDTCTL = WDTPW + WDTHOLD;
这里简单说下为啥这么写:
#define WDTPW (0x5A00u);,是看门狗的写入指令,必须有这个指令才能改变看门狗的控制位;
#define WDTHOLD (0x0080u);是看门狗的使能位,缺省是0为打开开门狗,置位则变成关闭看门狗;
下面的控制位也是这样可以查到响应的意思。
②定时计数模式:
定时计数模式分为八种计数模式:
/* WDT-interval times [1ms] coded with Bits 0-2 /
/ WDT is clocked by fSMCLK (assumed 1MHz) /
#define WDT_MDLY_32 (WDTPW+WDTTMSEL+WDTCNTCL) / 32ms interval (default) /
#define WDT_MDLY_8 (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS0) / 8ms " /
#define WDT_MDLY_0_5 (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1) / 0.5ms " /
#define WDT_MDLY_0_064 (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1+WDTIS0) / 0.064ms " /
/ WDT is clocked by fACLK (assumed 32KHz) /
#define WDT_ADLY_1000 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL) / 1000ms " /
#define WDT_ADLY_250 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS0) / 250ms " /
#define WDT_ADLY_16 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1) / 16ms " /
#define WDT_ADLY_1_9 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1+WDTIS0) / 1.9ms " */
这里写个简单的例子来说明:
我的电路上P2.0连接的是一个发光二极管,我这里用看门狗的计数器来控制发光二极管的亮灭;
#include "msp430x14x.h"
int main( void )
{
WDTCTL = WDT_ADLY_1000; //使用了32768hz来控制计数,这里间隔是1S
IE1 |= WDTIE; // Enable WDT interrupt
P2DIR = 0x01; // Set P2.0 to output direction
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupt
}
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
P2OUT ^= BIT0; // Toggle P2.0 using exclusive-OR
}
所以每隔1S启动看门狗的中断函数,执行看门狗中断函数;
③作为看门狗模式:
看门狗模式分为八种计数模式:
/* WDT is clocked by fSMCLK (assumed 1MHz) /
#define WDT_MRST_32 (WDTPW+WDTCNTCL) / 32ms interval (default) /
#define WDT_MRST_8 (WDTPW+WDTCNTCL+WDTIS0) / 8ms " /
#define WDT_MRST_0_5 (WDTPW+WDTCNTCL+WDTIS1) / 0.5ms " /
#define WDT_MRST_0_064 (WDTPW+WDTCNTCL+WDTIS1+WDTIS0) / 0.064ms " /
/ WDT is clocked by fACLK (assumed 32KHz) /
#define WDT_ARST_1000 (WDTPW+WDTCNTCL+WDTSSEL) / 1000ms " /
#define WDT_ARST_250 (WDTPW+WDTCNTCL+WDTSSEL+WDTIS0) / 250ms " /
#define WDT_ARST_16 (WDTPW+WDTCNTCL+WDTSSEL+WDTIS1) / 16ms " /
#define WDT_ARST_1_9 (WDTPW+WDTCNTCL+WDTSSEL+WDTIS1+WDTIS0) / 1.9ms " */
给个简单的例子,来对比之前的是方式:
#include "msp430x14x.h"
int main( void )
{
WDTCTL = WDT_ARST_1000;
IE1 |= WDTIE; // Enable WDT interrupt
P2DIR = 0x01; // Set P2.0 to output direction
P2OUT ^= BIT0;
__bis_SR_register(LPM3_bits + GIE); // Enter LPM0 w/ interrupt
}
这里不用单独写中断函数,因为技术超出之后,只要ifg置位,则单片机软复位。
上面两个例子的实验结果相同,但是实现方式不同,注意看WDTCTL后面的赋值语句,两种赋值语句是不同的。
三种模式讲完了,下面讲下官方给的案例:
//******************************************************************************
// MSP-FET430P140 Demo - WDT, Toggle P1.0, Interval Overflow ISR, DCO SMCLK
//
// Description: Toggle P1.0 using software timed by the WDT ISR. Toggle rate
// is approximately 30ms based on default ~ 800khz DCO/SMCLK clock source
// used in this example for the WDT.
// ACLK= n/a, MCLK= SMCLK= default DCO~ 800k
//
// MSP430F149
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | P1.0|-->LED
//
// M. Buccini
// Texas Instruments Inc.
// Feb 2005
// Built with IAR Embedded Workbench Version: 3.21A
//******************************************************************************
#include
void main(void)
{
WDTCTL = WDT_MDLY_32; // Set Watchdog Timer interval to ~30ms
IE1 |= WDTIE; // Enable WDT interrupt
P1DIR |= 0x01; // Set P1.0 to output direction
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
// Watchdog Timer interrupt service routine
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR
}
上面的例子和我的写的例子基本一个意思;
//******************************************************************************
// MSP-FET430P140 Demo - WDT, Toggle P1.0, Interval Overflow ISR, 32kHz ACLK
//
// Description: Toggle P1.0 using software timed by WDT ISR. Toggle rate is
// exactly 250ms based on 32kHz ACLK WDT clock source. In this example the
// WDT is configured to divide 32768 watch-crystal(2^15) by 2^13 with an ISR
// triggered @ 4Hz.
// ACLK= LFXT1= 32768, MCLK= SMCLK= DCO~ 800kHz
// //* External watch crystal installed on XIN XOUT is required for ACLK *//
//
// MSP430F149
// -----------------
// /|\| XIN|-
// | | | 32kHz
// --|RST XOUT|-
// | |
// | P1.0|-->LED
//
// M. Buccini
// Texas Instruments Inc.
// Feb 2005
// Built with IAR Embedded Workbench Version: 3.21A
//******************************************************************************
#include
void main(void)
{
WDTCTL = WDT_ADLY_250; // WDT 250ms, ACLK, interval timer
IE1 |= WDTIE; // Enable WDT interrupt
P1DIR |= 0x01; // Set P1.0 to output direction
_BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/interrupt
}
// Watchdog Timer interrupt service routine
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR
}
上面的例子也是一样,只是选择了不同的时钟,而且低功耗模式不同;
//******************************************************************************
// MSP-FET430P140 Demo - WDT, Toggle P1.0, Interval Overflow ISR, HF XTAL ACLK
//
// Description: Toggle P1.0 using software timed by the WDT ISR. In this
// example the WDT is clocked with ACLK which is the same as the XTAL and
// divided by the WDT by 512 triggering and ISR that will toggle P1.0.
// ACLK= MCLK= LFXT1= HF XTAL
// //* HF XTAL REQUIRED AND NOT INSTALLED ON FET *//
// //* Min Vcc required varies with MCLK frequency - refer to datasheet *//
//
// MSP430F149
// -----------------
// /|\| XIN|-
// | | | HF XTAL (455k - 8Mhz)
// --|RST XOUT|-
// | |
// | P1.0|-->LED
//
// M. Buccini
// Texas Instruments Inc.
// Feb 2005
// Built with IAR Embedded Workbench Version: 3.21A
//******************************************************************************
#include
void main(void)
{
volatile unsigned int i;
WDTCTL = WDT_ADLY_16; // ACLK / 512, interval timer
BCSCTL1 |= XTS; // ACLK = LFXT1 = HF XTAL
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0xFF; i > 0; i--); // Time for flag to set
}
while ((IFG1 & OFIFG)); // OSCFault flag still set?
BCSCTL2 |= SELM_3; // MCLK = LFXT1 (safe)
IE1 |= WDTIE; // Enable WDT interrupt
P1DIR |= 0x01; // Set P1.0 to output direction
_BIS_SR(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
// Watchdog Timer interrupt service routine
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR
}
先清空标志位,小延时一下。判断是否中断标志是否置位,标志位为0时执行循环,直到时钟源设置稳定,退出循环,执行中断函数,进入低功耗模式,等待中断唤醒。