WDT, (slau144.pdf, p.347)
In most cases Watchdog Timer (WDT) is used as an interrupt source. For example, the LED switches every second (inside WDT interrupt's cycle).
-- For seconds:
#include <msp430.h>
int main(void)
{
WDTCTL = WDT_ADLY_1000; // WDT 1000ms, ACLK = 32kHz, interval timer
BCSCTL1 = DIVA_0; // WDT (ACLK) clock divider, 0 is default
P1DIR |= 0x01;
IE1 |= WDTIE; // Enable WDT interrupt
__bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/interrupt
}
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR
}
Divider (DIVA_1, DIVA_2, DIVA_3) increases this time to 2, 4, 8 sec.
Additional 3 choices for WDT_ADLY_1000 : WDT_ADLY_250, ..._16, ..._1_9.
If 32kHz does not start (by some reasons), then it will be automatically replaced by internal 12 kHz VLO. Intervals will increase, respectively, 32/12=2.7 times.
-- For mili-seconds:
The next, all the same, only the clock source - SMCLK. The only difference is that you can put controller only in LPM0 (since SMCLK is turned off in all others).
#include <msp430.h>
int main(void)
{
WDTCTL = WDT_MDLY_32; // SMCLK, set Watchdog Timer interval to ~30ms
BCSCTL2 = DIVS_0; // WDT (SMCLK) clock divider, 0 is default
P1DIR |= 0x01;
IE1 |= WDTIE; // Enable WDT interrupt
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/interrupt
}
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR
}
The same, divider (DIVS_1, DIVS_2, DIVS_3) increases this time to 60, 120, 240 ms.
Additional 3 choices for WDT_MDLY_32 : WDT_MDLY_8, ..._0_5, ..._0_064.
-- For micro-seconds:
The clock source is directly tied to MCLK (DCOCLK), which by default is about 1 MHz. This frequency can be tuned from 100kHz to 20MHz. But we can use 4 calibrated frequencies - 1, 8, 12, and 16MHz.
#include <msp430.h>
int main(void)
{
WDTCTL = WDT_MDLY_32; // SMCLK, set Watchdog Timer interval to 32ms
BCSCTL1 = CALBC1_1MHZ; // or 8MHZ, 12MHZ, or 16MHZ
DCOCTL = CALDCO_1MHZ; // the same, 8MHZ, 12MHZ, or 16MHZ
P1DIR |= 0x01;
IE1 |= WDTIE; // Enable WDT interrupt
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/interrupt
}
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR
}
After increasing the frequency by 16 times, the intervals for WDT interrupt (32, 8, 0.5, and 0.064mS) will be decreased to 32mS/16=2mS, 0.5mS, 30uS, and 4uS.
-- For "Reset" intervals:
Exactly the same idea, only 'watchdog timer' generates a "Reset" signal and the program starts from the beginning, every time.
#include <msp430.h>
int main(void)
{ // WDT is clocked by fSMCLK (~1MHz)
WDTCTL = WDT_MRST_32; // ~32ms interval (default)
//WDTCTL = WDT_MRST_8; // ~8ms
//WDTCTL = WDT_MRST_0_5; // ~0.5ms
//WDTCTL = WDT_MRST_0_064; // ~0.064ms
// WDT is clocked by fACLK (32KHz)
//WDTCTL = WDT_ARST_1000; // 1000ms
//WDTCTL = WDT_ARST_250; // 250ms
//WDTCTL = WDT_ARST_16; // 16ms
//WDTCTL = WDT_ARST_1_9; // 1.9ms
P1DIR |= 0x01;
P1OUT ^=0x01;
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/int. if clocked by SMCLK
// __bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/interrupt if by ACLK
}