Jump to content
yyrkoon

msp430G2553 WDT

Recommended Posts

 

This( below ) is probably closer to how the WDT is meant to be used. But I do have a quesiton if anyone may know. How can one put the MCU in low power mode if we're constantly kicking the dog ? ~32ms is not a whole lot of time using fSMCLK, and fACLK is only available if you have an external crystal soldered on right ?

 

 

So I guess I'll answer my own question by mentioning something I said earlier. I'f I'm using a timer, a timer can run in low power mode, and can also service the watchdog . . . I guess I lost my brain for a few minutes there . . .

Share this post


Link to post
Share on other sites

OK, I got something working here, and if not too much trouble I'd appreciate some comments on this code. I'm still fumbling around a bit so I could use some pointers, any pointers anyone would wish to share with me, and the forum. Also, am I correct in that timer A0 can not be used in conjunction with the WDT, or am I remembering wrong ?

#include <msp430.h>

volatile unsigned int count = 1;

int main(void) {

        WDTCTL = WDTPW + WDTHOLD;       // stop watchdog timer

        P1DIR = 0x01;                   // set up bit 0 of P1 as output
        P1OUT = 0x00;                   // intialize bit 0 of P1 to 0

        TA1CCR0 = 3000;
        TA1CTL = TASSEL_2 + ID_3 + MC_1;

        TA1CCTL0 = CCIE;

        __enable_interrupt();
        WDTCTL = WDTPW | WDTCNTCL;      // Enable WDT

        while(1){
                LPM0;
                WDTCTL = WDTPW | WDTCNTCL;
                if (count > 10){
                    count = 1;
                    P1OUT ^= 0x01;
                }
        }

        return 0;
}

__attribute__( (interrupt (TIMER1_A0_VECTOR)) )
void TIMER1_A0_ISR(void)
{
        LPM0_EXIT;
        count++;
}

Share this post


Link to post
Share on other sites

You can source ACLK from the VLO (12 kHz internal oscillator), which timer is available as an interrupt source is dependent on its clock source and the low power mode used as the various modes shuts down different oscillators to save power. An external heartbeat can also be employed to reset the WDT, either as a clock source for a timer or as an input to an I/O pin (or even NMI) set up to generate an interrupt. So a lot of options are available, care has to be taken to choose one that works.

Share this post


Link to post
Share on other sites

@@bluehash

 

http://43oh.com/2010/09/msp430-interrupt-primer-watchdog-example/ <---- dead link at the bottom. From 2010 so no big surprise. This link in particular: http://justinstech.org/2010/09/msp430-coding-interrupts-for-mspgcc/

Fixed. Thank you. Looks like the link changed.

Share this post


Link to post
Share on other sites

Fixed. Thank you. Looks like the link changed.

Oh sweet ! you found the original link  . . . however it's dated info, and there's not much there unfortunately :(

Share this post


Link to post
Share on other sites

So, no one wishes to comment on my latest code above ? I know it's pretty minimal, but thats the point. A minimal skeleton to get a working timer + WDT working together. . . .

Share this post


Link to post
Share on other sites

Additionally, I'm kind of slacking off today on this project, but will probably start reading the msp430x2xxx literature to understand a few concepts better.

Share this post


Link to post
Share on other sites

Update:

 

I've been busy the last couple days, but tonight I've got around to reading some documentation on the timers, and I think I've got it where I want it . . .

#include <msp430.h>

volatile unsigned int count = 1;

int main(void)
{

        WDTCTL = WDTPW + WDTHOLD;               // stop watchdog timer
        
        DCOCTL = 0;
        DCOCTL = CALDCO_1MHZ;
        BCSCTL1 = CALBC1_1MHZ;
        BCSCTL2 = DIVS_0;


        P1DIR = 0x01;                           // set up bit 0 of P1 as output
        P1OUT = 0x00;                           // intialize bit 0 of P1 to 0

        TA1CCR0 = 1250;                         // Count overflow frequency
        TA1CTL = TASSEL_2 + ID_3 + MC_1;        // SMCLK/8  upmode
                                                // ( 1000000 / 8 ) / 1250 == 10ms tick
        TA1CCTL0 = CCIE;

        __enable_interrupt();
        WDTCTL = WDTPW | WDTCNTCL;              // Enable WDT
        
        while(1){
                LPM0;
                WDTCTL = WDTPW | WDTCNTCL;
                if (count > 100){               // ~1 Second
                    count = 1;
                    P1OUT ^= 0x01;
                }
        }

        return 0;
}

__attribute__( (interrupt (TIMER1_A0_VECTOR)) )
void TIMER1_A0_ISR(void)
{
        LPM0_EXIT;
        count++;
}

 

Share this post


Link to post
Share on other sites

*OR* How about reading from channel 5 of the ADC, and logging it out over UART every ~second ?

#include <msp430.h>
#include <stdlib.h>
#include "hw_serial.h"

using namespace uart;

volatile unsigned int count = 1;

int main(void)
{

        WDTCTL = WDTPW + WDTHOLD;               // Stop watchdog timer

        UART<9600, 1000000> Serial;
        /* SMCLK */
        DCOCTL = 0;
        DCOCTL = CALDCO_1MHZ;
        BCSCTL1 = CALBC1_1MHZ;
        BCSCTL2 = DIVS_0;

        /* ADC */
        P1SEL |= BIT5;
        ADC10CTL1 = INCH_5 + ADC10DIV_3 ;
        ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON;
        ADC10AE0 |= BIT5;

        /* Timer1 A0*/
        TA1CCR0 = 1250;                         // Count overflow frequency
        TA1CTL = TASSEL_2 + ID_3 + MC_1;        // SMCLK/8  upmode
                                                // ( 1000000 / 8 ) / 1250 == 10ms tick
        TA1CCTL0 = CCIE;

        __enable_interrupt();
        WDTCTL = WDTPW | WDTCNTCL;              // Enable WDT

        Serial.Initialize();

        int sample = 0;

        while(1){
                LPM0;
                WDTCTL = WDTPW | WDTCNTCL;
                if (count > 100){               // ~1 Second
                        count = 1;
                        __delay_cycles(1000);                // Wait for ADC Ref to settle
                        ADC10CTL0 |= ENC + ADC10SC;            // Sampling and conversion start
                        sample = ADC10MEM;
                        Serial.Write(sample, 10);
                        Serial.Write("\r");
                }
        }

        return 0;
}

__attribute__( (interrupt (TIMER1_A0_VECTOR)) )
void TIMER1_A0_ISR(void)
{
        LPM0_EXIT;
        count++;
}


 

Share this post


Link to post
Share on other sites

@@yyrkoon

 

I've noticed that you have a special serial library:

#include "hw_serial.h"

and that you use it like this:

UART<9600, 1000000> Serial;

This fascinates me.

Share this post


Link to post
Share on other sites

@@yyrkoon

 

I've noticed that you have a special serial library:

#include "hw_serial.h"

and that you use it like this:

UART<9600, 1000000> Serial;

This fascinates me.

It's C++  . . . and quite honestly I've forgotten most of how it works. But it's code I adapted from @@Rickta59, or @@oPossum . . . been a while I forget all the details. But you can see the header file here: http://forum.43oh.com/topic/3247-simple-serial-minimal-debugging/?p=29583

 

@@Rickta59 actually had print routines that took up half as much flash in binary form than this. But this was a product of code written by, again honestly I do recall, but I did adapt it myself. I was super heavy into learning C++ template code at the time. After @@oPossums demonstration of I think a Nokia LCD driver file he wrote entirely in C++ templates. Also @@Rickta59 was sort of coaching me with all of this . . .

Share this post


Link to post
Share on other sites

@@zeke

 

If you did use this code, and required numbers . . . this is actually what you'd want. http://forum.43oh.com/topic/3247-simple-serial-minimal-debugging/?p=29661

 

One caveat, I'm not sure if it will print float values or not. I ran into some trouble last night where my code was writing out "0" instead of a floating point value. I do know that there is a compiler glitch if a number is not declared as a float and you do math of integers + floats, your result may come out as zero, if not done right. But I double checked my code, and am pretty sure I was not running into that issue . .

Share this post


Link to post
Share on other sites

Now for some reason after installing handbrake to transcode the video into a smaller file, and havng it crash my system . . . I'm no longer able get serial out from the launchpad . . . looking into why. . .

Share this post


Link to post
Share on other sites

@@yyrkoon

 

I've noticed that you have a special serial library:

#include "hw_serial.h"

and that you use it like this:

UART<9600, 1000000> Serial;

This fascinates me.

 

His implementation is very simple but not so flexible. You can find a more complete c++ template implementation here:

 

https://github.com/RickKimball/fabooh/blob/master/examples/serial/ascii_table_iostream/ascii_table_iostream.cpp - ascii table dump using operator insertion or standard function calls

https://github.com/RickKimball/fabooh/tree/master/examples/math .. sine table prints using cordic, fixed math and floats

 

fabooh support eusci, usci, software only (on any pin) with multiple instances and finally timer based serial.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×