This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Bytes missing during UART transmission

Other Parts Discussed in Thread: MSP430F5529, MSP430G2553

Hi all,

I am trying to transmit data to a PC through UART under BR 460800 using MSP430f5529 lauchpad. In the PC side, matlab serial module is used for data collecting. The data transmitted (int type) goes up from 0 to 65535 and goes back down to 0. The process iterates until  2621400 data is sent out. While in the matlab side, for example, the data received is 2582206. 39194 of data are missed. There are three places where the received data does not increase smoothly. For example, the received bytes are (195 25 195 26 195 27 222 229 221 229). I am struggling with this problem. My application is to send out data from ADC to a PC through UART consistently. The transmission time would be as long as 1 hour. I have to figure out the missing data problem or the data collected can not be trusted.

The code is shown below. 

#include <msp430.h>
unsigned int ADCdata;
unsigned int count=0;
unsigned char up=1;
int main(void)
{

WDTCTL = WDTPW+WDTHOLD; // Stop WDT

ADCdata=0;
P3SEL |= BIT3+BIT4;


UCSCTL3 = SELREF_2; // Set DCO FLL reference = REFO
UCSCTL4 |= SELA_2; // Set ACLK = REFO
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx

// Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag

__bis_SR_register(SCG0); // Disable the FLL control loop
UCSCTL1 = DCORSEL_5; // Select DCO range 20MHz operation
UCSCTL2 |= 609; // Set DCO Multiplier for 20MHz
__bic_SR_register(SCG0); // Enable the FLL control loop

__delay_cycles(250000);


/*UCA0 UART Initialization*/
UCA0CTL1 |= UCSSEL_2+UCSWRST; // CLK = SCLK
UCA0BR0 = 43; // 20MHz 480600
UCA0BR1 = 0; // 20MHz 480600
UCA0MCTL =UCBRS_3; // Modulation UCBRSx = 3
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**

while(1)
{
UCA0TXBUF= ADCdata>>8;
while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = ADCdata; // TX -> RXed character
while (!(UCA0IFG&UCTXIFG));
if(up==1)
ADCdata=ADCdata+1;
else
ADCdata=ADCdata-1;
if (ADCdata==0xFFFF)
{
up=0;
}
else if (ADCdata==0x0000)
{
up=1;
count=count+1;
}
if (count==20)
{
UCA0CTL1 |= UCSWRST;
}
}
}

  • Hi Huanhuan!

    I have never seen anyone using such a high baudrate. Do you need it that high? It is fault-prone. Anyway...

    Next time when posting code please insert it using this symbol:

    It appears in the menu bar when using richt text formatting for posting messages. Thanks in advance!

    Your code (this is how it looks like when using the syntax highlighter - looks better, doesn't it?):

    #include <msp430.h>
    
    unsigned int  ADCdata;
    unsigned int  count = 0;
    unsigned char up    = 1;
    
    int main( void )
    {
      WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    
      ADCdata = 0;
    
      P3SEL |= BIT3 + BIT4;
    
      UCSCTL3  = SELREF_2; // Set DCO FLL reference = REFO
      UCSCTL4 |= SELA_2;   // Set ACLK = REFO
      UCSCTL0  = 0x0000;   // Set lowest possible DCOx, MODx
    
      do // Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
      {
        UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2, XT1, DCO fault flags
        SFRIFG1 &= ~OFIFG;                          // Clear fault flags
      } while( SFRIFG1 & OFIFG );                   // Test oscillator fault flag
    
      __bis_SR_register( SCG0 ); // Disable the FLL control loop
      UCSCTL1 = DCORSEL_5;       // Select DCO range 20MHz operation
      UCSCTL2 |= 609;            // Set DCO Multiplier for 20MHz
      __bic_SR_register( SCG0 ); // Enable the FLL control loop
    
      __delay_cycles( 250000 );
    
      /*UCA0 UART Initialization*/
      UCA0CTL1 |=  UCSSEL_2 + UCSWRST; // CLK = SCLK
      UCA0BR0   =  43;                 // 20MHz 480600
      UCA0BR1   =  0;                  // 20MHz 480600
      UCA0MCTL  =  UCBRS_3;            // Modulation UCBRSx = 3
      UCA0CTL1 &= ~UCSWRST;            // **Initialize USCI state machine**
    
      while( 1 )
      {
        UCA0TXBUF = ADCdata >> 8;
        while( !(UCA0IFG & UCTXIFG) ); // USCI_A0 TX buffer ready?
        UCA0TXBUF = ADCdata;           // TX -> RXed character
        while( !(UCA0IFG & UCTXIFG) );
    
        if( up == 1 )
          ADCdata = ADCdata + 1;
        else
          ADCdata = ADCdata - 1;
    
        if( ADCdata == 0xFFFF )
        {
          up = 0;
        }
        else if( ADCdata == 0x0000 )
        {
          up = 1;
          count = count + 1;
        }
    
        if( count == 20 )
        {
          UCA0CTL1 |= UCSWRST;
        }
      }
    }

    I'm running your program on a G2553 at the moment. But this takes some time since I am only using 9600 baud and you are sending over 5.2 million bytes. At the moment I have no idea how to find an error in this mass of data :-) From the code I cannot see a problem at first glance. Is it always the same pattern where the errors occur? Or is it randomly? Maybe your baudrate is too high and your receiver cannot handle it fast enough in some places or the timing fails after a while. Such high baudrates with asynchronous transmissions are always critical. The FLL maybe is not precise enough.

    I'm waiting for the output file of my transmission...but I don't think I will find anything in there.

    Dennis

  • If anyone wants to run this giant transmission on his LaunchPad himself, here is the code for the MSP430G2553:

    #include "msp430g2553.h"
    
    unsigned int  ADCdata;
    unsigned int  count = 0;
    unsigned char up    = 1;
    
    void main( void )
    {
      WDTCTL    =  ( WDTPW | WDTHOLD );                                        // Stop watchdog timer
    
      BCSCTL1   =  CALBC1_1MHZ;                                                // Set DCO range
      DCOCTL    =  CALDCO_1MHZ;                                                // Set DCO step and modulation
    	
      P1SEL     =  0x04;                                                       // Special function for P1.2 (TxD)
      P1SEL2    =  0x04;                                                       // Special function for P1.2 (TxD)
    
      UCA0CTL1  =  UCSWRST;                                                    // Set USCI A0 into software reset
      UCA0CTL1 |=  UCSSEL_2;                                                   // SMCLK as clock source
      UCA0BR0   =  104;                                                        // Clock prescaler 0 - refer to user's guide: commonly used baudrates
      UCA0BR1   =  0;                                                          // Clock prescaler 1
      UCA0MCTL  =  UCBRS_1;                                                    // Set modulation
      UCA0CTL1 &= ~UCSWRST;                                                    // Release USCI A0 from software reset
    
      while( 1 )
      {
        UCA0TXBUF = ADCdata >> 8;
        while( !(IFG2 & UCA0TXIFG) );
        UCA0TXBUF = ADCdata;
        while( !(IFG2 & UCA0TXIFG) );
    
        if( up == 1 )
          ADCdata = ADCdata + 1;
        else
          ADCdata = ADCdata - 1;
    
        if( ADCdata == 0xFFFF )
        {
          up = 0;
        }
        else if( ADCdata == 0x0000 )
        {
          up = 1;
          count = count + 1;
        }
    
        if( count == 20 )
        {
          UCA0CTL1 |= UCSWRST;
        }
      }
    }

  • , before you start thinking if I had nothing else to do again...I have! But this was easy now: I just used my setup I used for the ASCIImage-project I made for the Day:

    e2e.ti.com/.../665895

    The code is almost the same, I just deleted my transmission part and copied Huanhuan's one in. And now it transmits to my hterm as if it would send Jens' picture :-)

    Dennis
  • I don’t see the required Vcore setting for 20MHz in your software.
    Do you have the required capacitor connected to Vcore?
  • Huanhuan,

    My transmission has finished and I received 5.242.800 bytes. I scrolled briefly through it and everything looks fine. Maybe Leo is right and the problem is located in the oscillator of your micro and therefore the timing isn't good enough. Or the receiver side cannot handle it right.

    Dennis
  • Your Baud rate settings are also not optimized and will give a high error rate.
    Use a DCO frequency which comes closer to your baud rate.
    And/or using Oversampling Baud rate mode.

  • Thanks Dennis for you reply and thank you for your time. Next time I will use Syntax Highlighter as you suggested. In my application, I need to 460800 because my input signal for sampling is 10KHz. The error occurs randomly. Are your bytes fully received or missed somewhere?
  • I did not look at all 5.242.800 bytes, but at least the number is right: 65535 x 2 x 2 x 20 = 5.242.800

    Dennis
  • I got your result now. Thanks for the trying. Question is I set the clk of MSP430f5529 as 20MHz and do the UART setting based on data sheet. I even sent the clk to I/O and check it using oscilloscope which shows that the period of clk is 50.3ns (should be close enough). What else can I do to optimize the timing?
  • Thank you Leo for your advice. I have added the Vcore setting now. There is a 470nF capacitor added in Vcore pin on the lauchpad, so I can leave it there alone. Unfortunately, things are not getting better. Still missed some data. The code is shown below:

    #include <msp430.h>
    unsigned int ADCdata;
    unsigned int count=0;
    unsigned char up=1;
    
    void SetVcoreUp (unsigned int level);
    
    int main(void)
    {
    //  volatile unsigned int i;
    
      WDTCTL = WDTPW+WDTHOLD;                   // Stop WDT
    
    
      P3SEL |= BIT3+BIT4;
    
      // Increase Vcore setting to level3 to support fsystem=25MHz
       // NOTE: Change core voltage one level at a time..
       SetVcoreUp (0x01);
       SetVcoreUp (0x02);
       SetVcoreUp (0x03);
    
       //set the clk to 20MHz
    
       UCSCTL3 = SELREF_2;                       // Set DCO FLL reference = REFO
       UCSCTL4 |= SELA_2;                        // Set ACLK = REFO
       UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
    
       // Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
       do
       {
         UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                                 // Clear XT2,XT1,DCO fault flags
         SFRIFG1 &= ~OFIFG;                      // Clear fault flags
       }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
    
       __bis_SR_register(SCG0);                  // Disable the FLL control loop
       UCSCTL1 = DCORSEL_5;                      // Select DCO range 20MHz operation
       UCSCTL2 |= 609;                           // Set DCO Multiplier for 20MHz
                                                 // (N + 1) * FLLRef = Fdco
                                                 // (609 + 1) * 32768 = 20MHz
       __bic_SR_register(SCG0);                  // Enable the FLL control loop
    
       // Worst-case settling time for the DCO when the DCO range bits have been
       // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
       // UG for optimization.
       // 32 x 32 x 20 MHz / 32,768 Hz = 625000 = MCLK cycles for DCO to settle
       __delay_cycles(625000);
    
    
      ADCdata=0;
    
    
     /*UCA0 UART Initialization*/
         UCA0CTL1 |= UCSSEL_2+UCSWRST;                     // CLK = SCLK
    //     UCA0STAT |= UCLISTEN;
         UCA0BR0 = 43;                            // 20MHz 480600
         UCA0BR1 = 0;                              // 20MHz 480600
         UCA0MCTL =UCBRS_3;                        // Modulation UCBRSx = 3
    //     UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
     //    UCA0IE |= UCTXIE;                         // Enable USCI_A1 RX
         __bis_SR_register(GIE);       // Enter LPM1, Enable interrupts
       while(1)
       {
    		UCA0TXBUF= ADCdata>>8;
    		while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
    		UCA0TXBUF = ADCdata;                  // TX -> RXed character
    		while (!(UCA0IFG&UCTXIFG));
    		if(up==1)
    		ADCdata=ADCdata+1;
    		else
    			ADCdata=ADCdata-1;
    		if (ADCdata==0xFFFF)
    			{
    			up=0;
    			}
    		else if (ADCdata==0x0000)
    		{
    			up=1;
    			count=count+1;
    		}
    		if (count==20)
    		{
    			 UCA0CTL1 |= UCSWRST;
    		}
       }
    }
    
    void SetVcoreUp (unsigned int level)
    {
      // Open PMM registers for write
      PMMCTL0_H = PMMPW_H;
      // Set SVS/SVM high side new level
      SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
      // Set SVM low side to new level
      SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
      // Wait till SVM is settled
      while ((PMMIFG & SVSMLDLYIFG) == 0);
      // Clear already set flags
      PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
      // Set VCore to new level
      PMMCTL0_L = PMMCOREV0 * level;
      // Wait till new level reached
      if ((PMMIFG & SVMLIFG))
        while ((PMMIFG & SVMLVLRIFG) == 0);
      // Set SVS/SVM low side to new level
      SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
      // Lock PMM registers for write access
      PMMCTL0_H = 0x00;
    }
    
    

  • An optimal DCO frequency for your baud-rate would be 20,275,200MHz but this is not possible but with FLLN = 618 you get 20,283,392MHz.

    I know I’m very good in swapping values and therefore check these always very carefully multiple times, but I see I’m not the only one. In your first post you talk about baud rate 460,800 in the program you write 480,600 but uses (43) 460,800, which one is correct? I assume 460,800.

    Use Oversampling of the Baud Rate generator, this makes it possible to come closer to the desired bit-clock frequency. Set UCA0BR0 = 2, UCBRFx = 12 and UCBRSx = 0.

    In theory you are now closest to the desired baud rate, but due to tolerances it might be necessary to do minor changes.

  • On your receiving side, be able to handle corrupt data.  It happens.  

    Maybe send your data bytes plus a checksum, then have the the MSP430 wait for a single byte response from the other end acknowledging the transmission.  Retry if no ACK happens.

  • Hi Leo,

    Thank you for your post. The baud rate is 460800, sorry for the confusion. I tried as your suggested (FLL setting is 618, UCBR=2, UCBRF=12, UCBRS=0). Unfortunately, data are still missing somewhere. My code is as below.

    #include <msp430.h>
    unsigned int ADCdata;
    unsigned int count=0;
    unsigned char up=1;
    
    void SetVcoreUp (unsigned int level);
    
    int main(void)
    {
    //  volatile unsigned int i;
    
      WDTCTL = WDTPW+WDTHOLD;                   // Stop WDT
    
      P1DIR |= BIT1;
      P1IN  &= ~BIT1;
      P1OUT |= BIT1;
      P1IE  |= BIT1;
      P1IES |= BIT1;
    
      P3SEL |= BIT3+BIT4;
    
      P5SEL |= BIT4+BIT5;                       // Port select XT1
    
    
    
      // Increase Vcore setting to level3 to support fsystem=20MHz
       // NOTE: Change core voltage one level at a time..
       SetVcoreUp (0x01);
       SetVcoreUp (0x02);
       SetVcoreUp (0x03);
    
       //set the clk to 20MHz
    
       UCSCTL6 &= ~XT1OFF;                       // Set XT1 On
        UCSCTL6 |= XCAP_3;                        // Internal load cap
    
       UCSCTL3 = SELREF_0;                       // Set DCO FLL reference = REFO
       UCSCTL4 |= SELA_0;                        // Set ACLK = REFO
       UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
    
       // Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
       do
       {
         UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                                 // Clear XT2,XT1,DCO fault flags
         SFRIFG1 &= ~OFIFG;                      // Clear fault flags
       }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
    
       __bis_SR_register(SCG0);                  // Disable the FLL control loop
       UCSCTL1 = DCORSEL_5;                      // Select DCO range 20MHz operation
       UCSCTL2 |= 618;                           // Set DCO Multiplier for 20MHz
                                                 // (N + 1) * FLLRef = Fdco
    
       __bic_SR_register(SCG0);                  // Enable the FLL control loop
    
       // Worst-case settling time for the DCO when the DCO range bits have been
       // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
       // UG for optimization.
       // 32 x 32 x 20 MHz / 32,768 Hz = 625000 = MCLK cycles for DCO to settle
       __delay_cycles(625000);
    
      //P2DIR |= 0x01;
      //P1SEL |= BIT2;
      //P1DIR |= BIT2;
     // P6SEL |= 0x01;                            // Enable A/D channel A0
      ADCdata=0;
    
    
     /*UCA0 UART Initialization*/
         UCA0CTL1 |= UCSSEL_2+UCSWRST;                     // CLK = SCLK
    //     UCA0STAT |= UCLISTEN;
         UCA0BR0 = 2;                            // 20MHz 460800
         UCA0BR1 = 0;                              // 20MHz 460800
         UCA0MCTL =UCBRS_0+UCBRF_12+UCOS16;                        // Modulation UCBRSx = 3
    //     UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
     //    UCA0IE |= UCTXIE;                         // Enable USCI_A1 RX
         __bis_SR_register(GIE+LPM1_bits);       // Enter LPM1, Enable interrupts
       while(1)
       {
    		UCA0TXBUF= ADCdata>>8;
    		while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
    		UCA0TXBUF = ADCdata;                  // TX -> RXed character
    		while (!(UCA0IFG&UCTXIFG));
    		if(up==1)
    		ADCdata=ADCdata+1;
    		else
    			ADCdata=ADCdata-1;
    		if (ADCdata==0xFFFF)
    			{
    			up=0;
    			}
    		else if (ADCdata==0x0000)
    		{
    			up=1;
    			count=count+1;
    		}
    		if (count==20)
    		{
    			 UCA0CTL1 |= UCSWRST;
    		}
       }
    }
    
    void SetVcoreUp (unsigned int level)
    {
      // Open PMM registers for write
      PMMCTL0_H = PMMPW_H;
      // Set SVS/SVM high side new level
      SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
      // Set SVM low side to new level
      SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
      // Wait till SVM is settled
      while ((PMMIFG & SVSMLDLYIFG) == 0);
      // Clear already set flags
      PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
      // Set VCore to new level
      PMMCTL0_L = PMMCOREV0 * level;
      // Wait till new level reached
      if ((PMMIFG & SVMLIFG))
        while ((PMMIFG & SVMLVLRIFG) == 0);
      // Set SVS/SVM low side to new level
      SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
      // Lock PMM registers for write access
      PMMCTL0_H = 0x00;
    }
    
    

     

  • Thank you James for your reply. In my application, I need UART to transmit fast. If I do what you mentioned, the data throughput would decrease. If I cannot find a way to solve this problem, I would like to slow down data transmission speed. I have a question: what does people usually do for fast data recording?
  • But now you start to mix-up the things. You have now enabled XT1! But XT1 is not started properly.

    If you want to try different way’s, you can create different Build Configuration for them so you can easy switch between them.

    Now clarify first what are you using and at which speed.
  • The "A" in UART stands for "asynchronous", which means that the interface does not have a clock signal, and that both devices need to have their own clocks that are accurate enough to match.

    The easiest synchronous data transfer mechanisms used by microcontrollers are protocols like I²C and SPI, which have separate clock lines. (SPI is used for SD cards.) However, it is difficult to interface with a PC using these.

    The F5529 supports USB. It's only full speed, but if that is enough, try using it.

  • Agree! But there are ways to ‘synchronize’ the UART baud-rate.
    With wrong software and/or hardware (cables) neither one of this will work properly especially with this high speed. So first things first.
  • Huanhuang,

    Just for testing: You could try using the UART without the FLL by sourcing the USCI directly from the 4MHz resonator. The baudrate is then 230400 and the timing error isn't that good as well, but maybe you will get a stable communication.

    Dennis

**Attention** This is a public forum