• Category Archives MSP430
  • Hardware » MSP430
  • MSP430: VLO and You!!

    So what is the VLO? The VLO is the very low- freq Oscillator, low power and low frequency(12KHz). So how does this change things, well now you can source your clocks from the DCO or the VLO instead of the 32Khz watch crystal. …….and now your asking yourself “Do I really need another clock source?” I say “yes!!”

    Now what can you do or how can i use the VLO? Its super easy to setup the VLO. In the Family user guide for the MSP430, Basic Clock Module+ will be your reference to set up the VLO.
    Registers that you will be concerned about are BCSCTL2, BCSCTL3 and the special functions registers.

    Setup

    • BCSCTL3 needs LFXT1S_2 to be set

    BCSCTL3 |= LFXT1S_2;                      // LFXT1 = VLO

    • BCSCTL2 needs to be set

    BCSCTL2 |= SELM_3 + SELS;                 // SMCLK  = MCLK = VLO = 12Khz

    • Clear OSC fault flag

    IFG1 &= ~OFIFG;                           // Clear OSCFault flag

    • Turn off DCO if not used

    _BIS_SR(SCG1 + SCG0);                // Stop DCO

     

    And that is all you need to do to setup your msp430 to use the VLO for SMCLK, AMCLK and MCLK @ 12KHz.  So now you need more control. so here are your VLO options

    BCSCTL1 –  controls XTS(not avalable on msp430x20xx), Divider for ACLK, and DCO range select.

    • DIVAx  – divide ACLK source by 1,2,4,8 or 00, 01, 10, 11(bit settings). Pretty much this will divide your Clock source by 1 – 8. This setting is just for ACLK which will be the crystal or VLO. (this only affects ACLK)
    • XTS, XT2OFF, and RSELx are not used for VLO but may be a good idea to read up on what they do.

     

     

    BCSCTL2  – controls MCLK divider, SMCLK divider MCLK and SMCLK clock source, each one is configurable.

    • SELMx – selects MCLK clock source, your choices are DCOCLK or LFXT1CLK/VLOCLK  just remember you cant use the VLO and the crystal
    • DIVMx – MCLK divider, divides the clock source by given amount, 1,2,4,8
    • SELS – select SMCLK source  DCOCLK or LFXT1CLK/VLOCLK
    • DIVSx – look another Divider, this one is for SMCLK
    • DCOR- not used – sets DCO resister to internal or external

     

    BCSCTL3 – XT and LFXT setting, only one setting is really used here.

    • LFXT1Sx – source of LFXT1,  00(0) for 32KHz crystal and  10(2) for VLO instead of the crystal
    • XT2Sx, XCAPx, XT2OF, LFXT1OF are not set or used for the VLO

     

     

    So now you have a basic understanding on how to setup your VLO, now let me give you a quick  VLO test

     

    /* VLO clock as main source instead of the DCO */
    #include  <msp430x20x3.h>
    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
    BCSCTL3 |= LFXT1S_2;                      // LFXT1 = VLO
    IFG1 &= ~OFIFG;                           // Clear OSCFault flag
    __bis_SR_register(SCG1 + SCG0);           // Stop DCO
    BCSCTL2 |= SELM_3;               // MCLK = LFXT1
    P1DIR |= 0x01;                            // Set P1.0 to output direction
    for (;;)
    {
    volatile unsigned int i;
    P1OUT ^= 0x01;                          // Toggle P1.0 using exclusive-OR
    i = 50000;                              // Delay
    do (i--);
    while (i != 0);
    }
    }

    code for use with mspgcc

     

    Now that we have the basics down on the VLO, what are some of the uses for it? Really low power clock, or a 3rd clock source that’s a different frequency then the main, really slow ADC conversions, odd SDA16 filter frequency, a low frequency tone generator.

     

    What other uses can you find? Let me know in the comments 🙂


  • 430 work shop links and source code

    source code zip of all the projects that were demoed at workshop 88 http://www.workshop88.com/
    demos
    (the code is in mspgcc format and may need alterations to compile for CCS & IAR)

    Sources code for Shift register demo
    original code here

    servo demo
    original source

    Music demo
    Original source here

    The RGB demo was not there
    source http://justinstech.org/projects/msp430-rgb-flower-pot/


  • more samples from TI :)

    MSP430F2013 – 16-bit Ultra-Low-Power Microcontroller, 2kB Flash, 128B RAM, 16-Bit Sigma-Delta A/D, USI for SPI/I2C
    MSP430F2013IN 2 of 2 part(s) Shipped 11 Nov 2010

    MSP430F2011 – 16-bit Ultra-Low-Power Microcontroller, 2kB Flash, 128B RAM, Comparator
    MSP430F2011IN 2 of 2 part(s) Shipped 11 Nov 2010

    MSP430F2012 – 16-bit Ultra-Low-Power Microcontroller, 2kB Flash, 128B RAM, 10-Bit SAR A/D, USI for SPI/I2C
    MSP430F2012IN 2 of 2 part(s) Shipped 11 Nov 2010

    MSP430G2221 – MSP430G2x21, MSP430G2x31 Mixed Signal Microcontroller
    MSP430G2221IN14 2 of 2 part(s) Shipped 11 Nov 2010

    MSP430G2231 – MSP430G2x21, MSP430G2x31 Mixed Signal Microcontroller
    MSP430G2231IN14 2 of 2 part(s) Shipped 11 Nov 2010


  • rgb v0.2

    I have finally gotten my RGB led to cycle through all 3 colors, i now just have to finish the board


    #include <msp430x20x2.h>
    #include <signal.h> //add for interrupt
    #define UP 0x00
    #define DOWN 0x01
    #define HOLD 0x02
    #define PERIOD 200 //sets period length-- PERIOD x interval length
    volatile  int millsecs = 0;
    volatile  int counter2 = 0;
    volatile  int led_red = 1;
    volatile  int led_green = 1;
    volatile  int led_blue = 1;
    volatile  int red = UP;
    volatile  int blue = HOLD;
    volatile  int green = HOLD;
    void main(void)
    {
    WDTCTL = WDT_MDLY_0_064;
    P1DIR |= BIT5 + BIT4 + BIT3;
    P1OUT |= BIT5 + BIT4 + BIT3;
    IE1 |= WDTIE;
    eint();
    }//end main
    interrupt(WDT_VECTOR) watchdog_timer(void)
    {
    ++millsecs;
    if (millsecs == PERIOD) { millsecs= 0; P1OUT |= BIT5 + BIT4 + BIT3; ++counter2; }
    if (millsecs == led_red ) { P1OUT ^= BIT3; }
    if (millsecs == led_green) { P1OUT ^= BIT4; }
    if (millsecs == led_blue ) { P1OUT ^= BIT5; }
    if (counter2 == 5 ) { counter2 =0;
    switch (red){
    case UP: ++led_red;
    if (led_red == 199) {red = HOLD; green = UP; blue = DOWN;}
    break;
    case DOWN: --led_red;
    if (led_red == 0) {red = HOLD;}
    break;
    case HOLD: break;
    }//end switch
    switch (blue){
    case UP:  ++led_blue;
    if (led_blue == 199) {blue = HOLD; green = DOWN; red = UP;}
    break;
    case DOWN: --led_blue;
    if (led_blue == 0) {blue = HOLD;}
    break;
    case HOLD: break;
    }//end switch
    switch (green){
    case UP: ++led_green;
    if (led_green == 199) {green = HOLD; red = DOWN; blue = UP;}
    break;
    case DOWN: --led_green;
    if (led_green == 0) {green = HOLD;}
    break;
    case HOLD: break;
    }//end switch
    }//end if
    }//end interrupt


  • MSP430 RGB V0.1

    A different take on how to create a PWM signal. I decided to go the interrupt route using the WDT+ peripheral. I did this by setting it to the interval timer and putting all my counters and logic within the interrupt. The funny thing is  i have read that you shouldn’t put too much code into your interrupt, or something bad will happen.

    the resistors on the left, are 100 ohm resistors and the one on the right is a 470 ohm resistor to limit current for the RGB LED. connections on the uC that are used are pins 1.3, 1.4, 1.5 i have not decided which pins are what color, i will decide that on my final build.

    The test code will be improved this is just the compile and see if it works.- The best part , the code works lol .

    so let me know what you think on creating PWM with the interval timer instead of timer A.

    #include <msp430x20x2.h>
    #include <signal.h> //add for interrupt
    #define UP 0x00
    #define DOWN 0x01
    volatile  int millsecs = 0;
    volatile  int counter2 = 0;
    volatile  int led_red = 0;
    volatile  int led_green = 199;
    volatile  int led_blue = 199;
    volatile  int dir = UP;
    void main(void)
    {
    WDTCTL = WDT_MDLY_0_064;
    P1DIR |= BIT5 + BIT4 + BIT3;
    P1OUT |= BIT5 + BIT4 + BIT3;
    IE1 |= WDTIE;
    eint();
    }//end main
    interrupt(WDT_VECTOR) watchdog_timer(void)
    {
    ++millsecs;
    if (millsecs == 200) { millsecs= 0; P1OUT |= BIT0 + BIT6; ++counter2; }
    if (millsecs == led_red ) { P1OUT ^= BIT3; }
    if (millsecs == led_green) { P1OUT ^= BIT4; }
    if (millsecs == led_blue ) { P1OUT ^= BIT5; }
    if (counter2 == 25 ) { counter2 =0;
    switch (dir){
    case UP: ++led_red; --led_green; --led_blue;
    if (led_red == 199) {dir = DOWN;}
    break;
    case DOWN: --led_red; ++led_green; ++led_blue;
    if (led_red == 0) {dir = UP;}
    break;
    }//end switch
    }//end if
    }//end interrupt

    To change the Period length – change the 200 value to the period you want, you can also change it by setting the WDT interval to different intervals to change the period.
    to change the Duty cycle, change the led_[color] variable to anything between 0 and period length

    I am still working on trying to get it to cycle through all colors, and fade better when led_[color] is close to 0
    by far this project is not done, the board will be soldered up and pics will be presented. The end result should be code for WDT PWM, which could be used for servos, LEDs, or possibly communication, and i will have my flower pot back!


  • MSP430: what doesnt work…….

    This will be an on going post that will be constantly updated on what doesn’t work when coding for the msp430…….yes this will feature my failings lol.
    so for the first Failure……

    Project: RGB led fade to different colors with a ~4 hour timer
    This fail is a test program that i had created to test the software PWM using WDT+ and interrupts.
    CCFLAGS = -mendup-at=main
    -mendup-at=”function”—when main ends, it usually goes to stop program execution, but you can make it jump back to main when main exits. pretty much sets it up as a never ending loop. great if main is supposed to never exit or return.
    Code:

    #include<msp430x20x2.h>
    #include<signal.h> //interrupt SR
    volatile unsigned int timer1 = 0;
    void main(void) {
    WDTCTL = WDT_MDLY_32;
    P1DIR |= BIT0+BIT6;
    IE1 |= WDTIE;
    if (timer1==126) {
    timer1 = 0;
    P1OUT ^= BIT6;
    }//end if
    _BIS_SR(LPM0+GIE);
    }//end main
    interrupt(WDT_VECTOR) watch_dog_timer(void)
    {
    ++timer1;
    P1DIR ^= BIT0;
    } //end interrupt

    what it was supposed to do is cycle through the program, when the WDT causes an interrupt the timer is supposed to increment
    then once the timer reaches 126 it resets and toggles P1.6(green LED on launchpad)

    what it did is loop through, never servicing an interrupt, and looped with out doing anything……well almost nothing, timer1 never incremented but the main loop did compare timer1 to 126.
    for some reason the interrupt never gets serviced because it goes back to main and clears the WDT timer count, so then it runs it runs so quick that the interrupt that’s sitting there clears when it goes back to main…..
    Cause: my theory says my code maybe too short for it to call the interrupt fully.
    When i step through it the interrupt flags never get called, and before you know it the whole thing starts over again.
    Fix: none as of yet still testing

    Continue reading  Post ID 853


  • msp430- coding interrupts for mspgcc

    I am just an idiot, but thats my opinion. For those with MSPGCC compilers, we have a more difficult time finding code examples, and many of the code examples given either don’ explain very well (cryptic Coding, un-commented code) or they are for the CCS or IAR, and they dont use the same syntax as the MSPGCC compiler. So here is how to create an interrupt handler for non-PUC/POR interrupts.

    I will not go into interrupt vector masking, that is beyond me at this moment, but im not saying that i wont cover it later on, once i understand why you would want to mask it…..
    So lets start at what headers and other setup items you need before, creating the interrupt handler.
    First the signal.h has to be included into your code. #include<signal.h>
    this will give you access to the special function of
    interrupt(VECTOR ) service_routine (void) {/*interrupt code*/ }

    this is the same as #pragma vector=WDT_VECTOR
    __interrupt void watchdog_timer(void){ }

    These are the Defined vectors for interrupts right from the header files.(mspgcc headers)

    #define PORT1_VECTOR 4 /* 0xFFE4 Port 1 */
    #define PORT2_VECTOR 6 /* 0xFFE6 Port 2 */
    #define USI_VECTOR 8 /* 0xFFE8 USI */
    #define ADC10_VECTOR 10 /* 0xFFEA ADC10 */
    #define TIMERA1_VECTOR 16 /* 0xFFF0 Timer A CC1-2, TA */
    #define TIMERA0_VECTOR 18 /* 0xFFF2 Timer A CC0 */
    #define WDT_VECTOR 20 /* 0xFFF4 Watchdog Timer */
    #define NMI_VECTOR 28 /* 0xFFFC Non-maskable */

    all the interrupts should be self expainatory, vector = the source of the interrupt.

    since now we have all the basics we can now right a small program that uses interrupt, we will just create a small WDT interval timer.
    /*WDT interval timer- code based on msp430 examples*/
    //compiler=mspgcc
    #include<msp430x22x2.h>
    #include<signal.h> //interrupt service routine
    #include <io.h> //usually included on msp430 header, but for sfr register access.
    void main(void) {
    WDTCTL = WDT_MDLY_32; //~30mS intervals
    P1DIR |=BIT1;
    IE1 |= WDTIE; //enable interrupt
    _BIS_SR(LPM0_bits + GIE); //not low power mode and enable interrupts
    }//end of main
    //interrupt service routine
    interrupt(WDT_VECTOR) watchdog_timer(void)
    {
    P1OUT ^= BIT1;
    }//end of interrupt

    this should give you a good start on your Interrupts but there is still one thing that you may need. Changing the power modes when a interrupt is being serviced, the power mode will revert back to the power mode that it was in when the interrupt was called.
    There are 2 functions that we can use to clear or set power modes while in an interrupt.
    First one is to set the mode on exit of the routine, this is done by changing the copy of the status register that is saved to the stack. _BIS_SR_IRQ( ... )
    you would use this the same way you would use the _BIS_SR(…)

    The second one will clear the bits you select _BIC_SR_IRQ(...) same usage as the other, except it will just clear the bits not modify them.
    ***the use of _BIx_SR_IRQ() should only be used in an interrupt service request, the compiler will give you a warning but will produce the correct code if you use it anywhere else.***
    ****remember to enable Interrupts by using BIS_SR(GIE) or eint()****

    Edit 6-23-2011

    MSPGCC Uniarch branch of mspgcc has been released, It supports newer chips like the msp430G2453 (the newer 20pin DIPs) This is an initiative to unify the current branches of mspgcc. Interrupts for this version is slightly different. Once I test it or get confirmation from another user I will post the correct format for uniarch branch……but what would be better would be unify the branches so we don’t have so much confusion with these version discrepancies and nuances of the trees.

    As of right now uniarch is still being worked on and there and is not fully recommended unless you need support for the newer 20pin Dips (G2x53 G2x52).  Please don’t let my opinion dissuade your choice of compiler, mspgcc works great for me but uniarch may work better for you.

     

    Thank you Tissit for your Comment

    “In current gcc, you can (should) include msp430.c instead of the specific header and use the -m switches (in a Makefile) to tell the compiler which chip you’re using. It will find the right headers automatically. “

    If I forget something let me know and I will update


  • MSP430 basic coding/programing part 2 WDT+

    WDT is a very useful tool, as I explained before most of us will turn it off or use it as an interval timer. Timer_A has a similar timer function but more robust and more options.
    So today we will be going over WDT and timer_A registers, how to setup them up, how you use them is up the you.

    WDT is the watch dog timer, used for checking errors/faults, or software states, interval timer, interval interrupt, or what ever other uses you can think of.

    So lets start with the basic register WDTCTL
    This is the main register that will configure the WDT, bits 15-8 are the password register and 7-0 are for control. you need to set the password register before you can modify bits 7-0.
    to do this WDTCTL = WDTPW; // WDTPW = 0x5A00 or 01011010 00000000
    This will allow access to the 7-0 bits to configure the WDT. The rest of the registers are used to turn off, setup, change to interval mode, set interupts, change clock sources, and more.
    This next set of registers is taken from the slau144e.pdf from the TI website, this book explains how it all works and what the settings mean.

    WDTHOLD Bit 7 Watchdog timer+ hold. This bit stops the watchdog timer+. Setting
    WDTHOLD = 1 when the WDT+ is not in use conserves power.

  • 0 Watchdog timer+ is not stopped
  • 1 Watchdog timer+ is stopped
  • WDTNMIES Bit 6 Watchdog timer+ NMI edge select. This bit selects the interrupt edge for the
    NMI interrupt when WDTNMI = 1. Modifying this bit can trigger an NMI. Modify
    this bit when WDTIE = 0 to avoid triggering an accidental NMI.

  • 0 NMI on rising edge
  • 1 NMI on falling edge
  • WDTNMI Bit 5 Watchdog timer+ NMI select. This bit selects the function for the RST/NMI pin.

  • 0 Reset function
  • 1 NMI function
  • WDTTMSEL Bit 4 Watchdog timer+ mode select

  • 0 Watchdog mode
  • 1 Interval timer mode
  • WDTCNTCL Bit 3 Watchdog timer+ counter clear. Setting WDTCNTCL = 1 clears the count
    value to 0000h. WDTCNTCL is automatically reset.

  • 0 No action
  • 1 WDTCNT = 0000h
  • WDTSSEL Bit 2 Watchdog timer+ clock source select

  • 0 SMCLK
  • 1 ACLK
  • WDTISx Bits 1-0
    Watchdog timer+ interval select. These bits select the watchdog timer+
    interval to set the WDTIFG flag and/or generate a PUC.

  • 00 Watchdog clock source /32768
  • 01 Watchdog clock source /8192
  • 10 Watchdog clock source /512
  • 11 Watchdog clock source /64
  • Continue reading  Post ID 853