• Join
  • Sign In with my.TI Login
Texas Instruments
  • Products
  • Applications
  • Tools & Software
  • Support & Community
  • Sample & Buy
  • About TI
Sample & Purchase Cart Sample & Purchase Cart
  • Search
  • Advanced
TI E2E™ Community
  • Support Forums
  • Blogs
  • Groups
  • Videos
  • 简体中文
  • More ...
TI Home » TI E2E Community » Support Forums » Microcontrollers » MSP430™ Microcontrollers » MSP430 Ultra-Low Power 16-bit Microcontroller Forum » software uart with processor msp430f2013
Share
MSP430™ Microcontrollers
  • Forum
  • Announcements
  • E2E Wiki
Options
  • Subscribe via RSS
MSP430 Resources
  • MSP430 Product Folder
  • MSP-EXP430G2 - MSP430 LaunchPad Value Line Development kit
  • MSP430 Getting Started Guide
  • MSP430 Microcontroller Projects
  • More Resources >
  • software uart with processor msp430f2013

    software uart with processor msp430f2013

    This question is answered
    zhenyu xi
    Posted by zhenyu xi
    on Apr 26 2012 10:01 AM
    Prodigy95 points

    hallo,

    i have been working on the software uart with processor f2013 for a few days and still can't get it work correctly. I just found an original code from ti source code.  It suits the whole family msp430x20x3 and should also suits my processor.

    hier is the original codes:

    //******************************************************************************
    //  MSP430F20xx Demo - Timer_A, Ultra-Low Pwr UART 2400 Echo, 32kHz ACLK
    //
    //  Description: Use Timer_A CCR0 hardware output modes and SCCI data latch
    //  to implement UART function @ 2400 baud. Software does not directly read and
    //  write to RX and TX pins, instead proper use of output modes and SCCI data
    //  latch are demonstrated. Use of these hardware features eliminates ISR
    //  latency effects as hardware insures that output and input bit latching and
    //  timing are perfectly synchronised with Timer_A regardless of other
    //  software activity. In the Mainloop the UART function readies the UART to
    //  receive one character and waits in LPM3 with all activity interrupt driven.
    //  After a character has been received, the UART receive function forces exit
    //  from LPM3 in the Mainloop which echo's back the received character.
    //  ACLK = TACLK = LFXT1 = 32768Hz, MCLK = SMCLK = default DCO
    //  //* An external watch crystal is required on XIN XOUT for ACLK *//    
    //
    //               MSP430F20xx
    //            -----------------
    //        /|\|              XIN|-
    //         | |                 | 32kHz
    //         --|RST          XOUT|-
    //           |                 |
    //           |   CCI0B/TXD/P1.5|-------->
    //           |                 | 2400 8N1
    //           |   CCI0A/RXD/P1.1|<--------
    //
    #define RXD       0x02                      // RXD on P1.1
    #define TXD       0x20                      // TXD on P1.5

    //   Conditions for 2400 Baud SW UART, ACLK = 32768

    #define Bitime_5  0x06                      // ~ 0.5 bit length + small adjustment
    #define Bitime    0x0E                      // 427us bit length ~ 2341 baud

    unsigned int RXTXData;
    unsigned char BitCnt;

    void TX_Byte (void);
    void RX_Ready (void);

    //  M. Buccini / L. Westlund
    //  Texas Instruments Inc.
    //  October 2005
    //  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.40A
    //******************************************************************************

    #include  <msp430x20x3.h>


    void main (void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
      CCTL0 = OUT;                              // TXD Idle as Mark
      TACTL = TASSEL_1 + MC_2;                  // ACLK, continuous mode
      P1SEL = TXD + RXD;                        //
      P1DIR = TXD;                              //

    // Mainloop
      for (;;)
      {
      RX_Ready();                               // UART ready to RX one Byte
      _BIS_SR(LPM3_bits + GIE);                 // Enter LPM3 w/ interr until char RXed
      TX_Byte();                                // TX Back RXed Byte Received
      }
    }


    // Function Transmits Character from RXTXData Buffer
    void TX_Byte (void)
    {
      BitCnt = 0xA;                             // Load Bit counter, 8data + ST/SP
      while (CCR0 != TAR)                       // Prevent async capture
        CCR0 = TAR;                             // Current state of TA counter
      CCR0 += Bitime;                           // Some time till first bit
      RXTXData |= 0x100;                        // Add mark stop bit to RXTXData
      RXTXData = RXTXData << 1;                 // Add space start bit
      CCTL0 =  CCIS0 + OUTMOD0 + CCIE;          // TXD = mark = idle
      while ( CCTL0 & CCIE );                   // Wait for TX completion
    }


    // Function Readies UART to Receive Character into RXTXData Buffer
    void RX_Ready (void)
    {
      BitCnt = 0x8;                             // Load Bit counter
      CCTL0 = SCS + OUTMOD0 + CM1 + CAP + CCIE;   // Sync, Neg Edge, Cap
    }

    // Timer A0 interrupt service routine
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)
    {
      CCR0 += Bitime;                           // Add Offset to CCR0

    // TX
      if (CCTL0 & CCIS0)                        // TX on CCI0B?
      {
        if ( BitCnt == 0)
        CCTL0 &= ~ CCIE;                        // All bits TXed, disable interrupt
        else
        {
          CCTL0 |=  OUTMOD2;                    // TX Space
          if (RXTXData & 0x01)
          CCTL0 &= ~ OUTMOD2;                   // TX Mark
          RXTXData = RXTXData >> 1;
          BitCnt --;
        }
      }
    // RX
      else
      {
        if( CCTL0 & CAP )                       // Capture mode = start bit edge
        {
        CCTL0 &= ~ CAP;                         // Switch from capture to compare mode
        CCR0 += Bitime_5;
        }
        else
        {
        RXTXData = RXTXData >> 1;
          if (CCTL0 & SCCI)                     // Get bit waiting in receive latch
          RXTXData |= 0x80;
          BitCnt --;                            // All bits RXed?
          if ( BitCnt == 0)
    //>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
          {
          CCTL0 &= ~ CCIE;                      // All bits RXed, disable interrupt
          _BIC_SR_IRQ(LPM3_bits);               // Clear LPM3 bits from 0(SR)
          }
    //>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        }
      }
    }

    The only thing i changed is the header.(from #include  <msp430x20x3.h> to #include  "msp430f2013.h")

    and i set the baud rate to 2400. but it still did'nt work. Can some1  pls help me? tnx.

    Report Abuse
    • Reply
    You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    All Replies
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Apr 27 2012 07:07 AM
      Verified Answer
      Verified by zhenyu xi
      Guru141810 points

      Do you have the external 32768Hz crystal attached to XT1? Else ACLK won't run with the expected frequency (if at all, on some 2xx MSPs without VLO, it's simply dead then)

      _____________________________________
      Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.
      If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • zhenyu xi
      Posted by zhenyu xi
      on Apr 28 2012 12:35 PM
      Prodigy95 points

      Hi Michael,

      thank you for answer.  It doesn't have the external crystal. And i found out in the datasheet. When there is no external crystal, the ACLK is sourced from the VLO of 12 KHz. So i modified the Bitime from 0xE to 0x5 and keep the baud rate at 2400. But it still wont work.

      And in the code there are two definitions of Bitime. (#define Bitime_5  0x06                      // ~ 0.5 bit length + small adjustment
                                                                                                  #define Bitime    0x0E                      // 427us bit length ~ 2341 baud)

      What is the use of Bitime_5 in the RX function? Can i just replace it with Bitime?

      Thank you for your help!

      zhenyu Xi

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on Apr 30 2012 09:50 AM
      Verified Answer
      Verified by zhenyu xi
      Guru141810 points

      zhenyu xi
      When there is no external crystal, the ACLK is sourced from the VLO of 12 KHz

      Well, 12k is just an averaged value. It can range from 4k to 20k and has a large temperature coefficient too, so it is almost absolutely unusable for asynchronous timings. You may individually calibrate your bit timings for every single MSP, and it may work, but I really wouldn't use it.

      zhenyu xi
      What is the use of Bitime_5 in the RX function? Can i just replace it with Bitime?

      Bitime_5 is the time for ~1/2 bit. It is required so you can read a bit in the middle, while the beginning of a byte transfer is determined on teh edge of the start bit.
      And no, you cannot replace it with Bitime, or you would try to read the state of a bit on teh edge between two bits, not knoeing whether you still read the last or already the next bit.

      _____________________________________
      Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.
      If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • zhenyu xi
      Posted by zhenyu xi
      on May 01 2012 03:50 AM
      Prodigy95 points

      thanks a lot  for your help!

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • zhenyu xi
      Posted by zhenyu xi
      on May 02 2012 11:19 AM
      Prodigy95 points

      Hi Michael,

      sorry to bother you again. But i really have  a problem. It's still about the software uart. I switched the processor from msp430f2013 to msp430fg4168. I know it has hardware uart, but i still like to programm a software one for it. The clock is at 1MHz and the Baud rate is 9600.

      So, here is the problem. Like you said, the Bit_time_5 is the time for half a bit. So we can read the bit in the middle. And it should be about 52 (104 for one bit). But when i set it to 52, it doesn't work. Only when i set it to about 100 (95 to 120 would also work), it functions well.

      Even when it works, there is still problem. In the codes i deleted the transmitting part. And i add  " if(RXByte == 'a')   P2OUT ^= BIT0; " to the recieving part. If it recieves an "a", the processor toggles the output at pin2.0. This pin is connected to the oscilloscope so i can see a edge coming when an "a" is sent. I used Hterm als Hyper Terminal from the PC. In Hterm you can set the stop bits to 1 or 2. When i send the charactors bytewise, it works perfert with 1 or 2 stop bits.  But when send the charactors in series, it only works with 2 stopbits. For example, with 2 stopbits i send "aaa", and in the oscillosope i can see 3 edges. But with 1 stopbit, i can only see 1 edge.

      Actually i also tried this code together with the transmission code. It turns out to be the same. With 2 stopbits, when i send "aaa", i recieve exactly "aaa". With 1 stopbits, when i send "aaa", i recieve "axx".

      I also thought about it. Maybe when i sent the charactors in series, the startbit the of the second byte came too early. At this moment, the interrupt was still disabled, because the processor was still dealing with the first byte. This could lead to bits lost  of the second byte. But i'm not sure and couldn't figure out a way to solve it. Can you pls help me? Thank you in advance.

      Here are the codes i used:

      //********************************************************************************************

      #include "msp430fg4618.h"
      #include "stdbool.h"

      #define RXD BIT2 // RXD on P1.2
      #define Bit_time            104                     // 9600 Baud, SMCLK=1MHz (1MHz/9600)=104
      #define Bit_time_5      104                    // Time for half a bit.

      unsigned char BitCnt; // Bit count, used when transmitting byte
      unsigned int RXByte; // Value recieved once hasRecieved is set
      bool isReceiving; // Status for when the device is receiving
      bool hasReceived; // Lets the program know when a byte is received

      // Function Definitions
      void Transmit(void);

      void main(void)
      {
          WDTCTL = WDTPW + WDTHOLD; // Stop WDT
       
          P1DIR &= ~RXD;                       // Select input at recieving side
          P1IES |= RXD;                            // RXD low edge interrupt
          P1IFG &= ~RXD;                       // Clear RXD (flag) before enabling interrupt
          P1IE |= RXD;                             // Enable RXD interrupt


          P2DIR |= BIT0;                          // Select output direction
          P2OUT &= ~BIT0;                    // Output = 0
         
          isReceiving = false;              // Set initial values
          hasReceived = false;
            
          __bis_SR_register(GIE);        // interrupts enabled
          
              while(1)
              {
                  if (hasReceived)                           // If the device has recieved a value
                  {
                  hasReceived = false;                   // Clear the flag
                      
                      if(RXByte == 'a')
                      {    P2OUT ^= BIT0;                   // toggle the ouput at P2.0, it's only to check whether recieving is working well.
                      }
                  }

                  if (~hasReceived)                                        // Loop again if another value has been received
                   __bis_SR_register(CPUOFF + GIE);
                                              // LPM0, the ADC interrupt will wake the processor up. This is so that it does not
                                              // endlessly loop when no value has been Received.
              }  
          
      }

      // Port 1 interrupt service routine
      #pragma vector=PORT1_VECTOR
      __interrupt void Port_1(void)
      {
          isReceiving = true;
          P1IE &= ~RXD;                // Disable RXD interrupt
          P1IFG &= ~RXD;              // Clear RXD IFG (interrupt flag)
          TACTL = TASSEL_2 + MC_2;              // SMCLK, continuous mode
           CCR0 = TAR;                                         // Initialize compare register
             CCR0 += Bit_time_5;                        // Set time till first bit
          CCTL0 = OUTMOD1 + CCIE;             // disable transmission and enable the interrupt
          RXByte = 0;                                            // Initialize RXByte
          BitCnt = 0x9;                                          // Load Bit counter, 8 bits + ST
      }

      // Timer A0 interrupt service routine
      #pragma vector=TIMERA0_VECTOR
      __interrupt void Timer_A0 (void)
      {    
          
              CCR0 += Bit_time;                           // Add Offset to CCR0
           
              if ( BitCnt == 0)
              {
                 TACTL = TASSEL_2;                    // SMCLK, timer off (for power consumption)
               CCTL0 &= ~ CCIE ;                        // Disable interrupt
               isReceiving = false;
              
                  if ( (RXByte & 0x201) == 0x200)                 // Validate the start and stop bits are correct
                  {
                       RXByte = RXByte >> 1;                           // Remove start bit
                       RXByte &= 0xFF;                                     // Remove stop bit
                  
                       hasReceived = true;
                  
                       P1IFG &= ~RXD;                                    // clear RXD IFG (interrupt flag)
                       P1IE |= RXD;                                          // enabled RXD interrupt
                  }
                 __bic_SR_register_on_exit(CPUOFF);                        // Enable CPU so the main while loop continues
              }


              else
              {
                  
                  if ( (P1IN & RXD) == RXD)                        // If bit is set?
                  RXByte |= 0x400;                                       // Set the value in the RXByte
                  RXByte = RXByte >> 1;                             // Shift the bits down
                  BitCnt --;
              }
          
      }

      //********************************************************************************************

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    • Jens-Michael Gross
      Posted by Jens-Michael Gross
      on May 08 2012 09:01 AM
      Guru141810 points

      zhenyu xi
      hen i send the charactors bytewise, it works perfert with 1 or 2 stop bits.  But when send the charactors in series, it only works with 2 stopbits.

      This is obvious. A stopbit is just a bit-length time in which the lien is guaranteed to be idle, so the next start bit can generate a falling edge (in case the last bit wa a '0' bit, which of course cannot be followed by a falling edge for the start bit)

      But in your code, you replaced the 1/2 bit time by a full 1/1 bit time. So the code is done waiting at the very moment the next start bit comes (in case of one stopbit). And misses the falling edge. With two stopbits, you just added a 1-bit dfelay between two immediately following bytes, and now your software is ready for the next byte.
      Typing the characters one by one acts as if you added a few thousands of stopbits manually. :)

      However, I don't know why your code doesn't work with Bit_time_5 = 52. I didn't analyze the code in detail and , sorry, don't have the time to do it now.

      But why don't you try to go through the code by hand and 'simulate' what's happening, on a piece of paper? After doing so, you should exactly know how the code works and why. And likely you'll also know where your problem is. I usually do it the same way.

      _____________________________________
      Before posting bug reports or ask for help, do at least quick scan over this article. It applies to any kind of problem reporting. On any forum. And/or look here.
      If you cannot discuss your problem in the public, feel free to start a private conversation: click on my name and then 'start conversation'. But please do so only if you really cannot do it in a public thread, as I usually read all threads. And I prefer to answer where others can profit from it (or contribute to it) too.

      Report Abuse
      • Reply
      You have posted to a forum that requires a moderator to approve posts before they are publicly available.
    TI E2E™ Community
    • Support Forums
    • Blogs
    • Videos
    • Groups
    • Site Support & Feedback
    • Settings
    TI E2E™ Community Groups
    • TI University Program
    • Make the Switch
    • Microcontroller Projects
    • Motor Drive & Control
    Other Communities
    • Deyisupport
    • Designsomething.org
    • beagleboard.org
    • TI on Element 14
    • TI on TechXchangeSM
    Other Technical & Support Resources
    • WEBENCH® Design Center
    • Product Information Centers
    • Technical Documents
    • TI Design Network
    • TI Technical Articles
    • TI Training

    All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.

    Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI, its suppliers and providers of content reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.

    Follow Us Texas Instruments on Facebook Texas Instruments on Twitter Texas Instruments on LinkedIn Texas Instruments on Google+
    TI Worldwide | Contact Us | my.TI Login | Site Map | Corporate Citizenship | mobile m.ti.com (Mobile Version)

    TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs and
    embedded processors, along with software, tools and the industry’s largest sales/support staff.

    © Copyright 1995-2013 Texas Instruments Incorporated. All rights reserved.
    Trademarks | Privacy Policy | Terms of Use