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.

UART transmit missing byte

Other Parts Discussed in Thread: MSP430G2553

Currently I am working on a project that sampling from ADC them transmit data to PC through UART....First step: Sampling from ADC10 channel 0

                   Transmit data from UART

Second step:  Sampling from ADC10 channel 10

                    Transmit data from UART

Third Step: Loop Back to channel 0

I choose baudrate = 9600, after sending about a few hundred byte, it will miss one byte, some times it will continuous missing bytes.There is no patten of data missing. Could you please tell me what could be the problem? Thanks a lot!

my orignal code is

#include <msp430.h>
int Temp_Humidity_Switch;
int ADC_Result;
char Byte0,Byte1;
int a,b,c;
int main(void)
{
  Temp_Humidity_Switch=0;

  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  ADC10CTL1 = INCH_0;
  ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10IE +  + ADC10ON ;


  P1DIR = 0X00;
  P1DIR |= BIT4 + BIT5 + BIT7;
  P1SEL = BIT6 + BIT7 + BIT5 + BIT1+BIT2;
  P1SEL2 = BIT6 + BIT7 + BIT5 + BIT1+BIT2;

  __enable_interrupt();                     // Enable interrupts.
  TACCR0 = 30;                              // Delay to allow Ref to settle
  TACCTL0 |= CCIE;                          // Compare-mode interrupt.
  TACTL = TASSEL_2 | MC_1;                  // TACLK = SMCLK, Up mode.
  LPM0;                                     // Wait for delay.
  TACCTL0 &= ~CCIE;                         // Disable timer Interrupt
  __disable_interrupt();
  ADC10CTL1 = INCH_0;                       // input A1
  ADC10AE0 |= 0x01;                         // PA.1 ADC option select
  //P1DIR |= 0x01;                            // Set P1.0 to output direction

  if (CALBC1_1MHZ==0xFF)                    // If calibration constant erased
  {
    while(1);                               // do not load, trap CPU!!
  }
  DCOCTL = 0;                               // Select lowest DCOx and MODx settings
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
  DCOCTL = CALDCO_1MHZ;

  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
  UCA0BR0 = 104;                            // 1MHz 9600
  UCA0BR1 = 0;                              // 1MHz 9600
  UCA0MCTL = UCBRS0;                        // Modulation UCBRSx = 1
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**


  for (;;)
  {
      switch(Temp_Humidity_Switch)
      {
      case 0:
          ADC10CTL0 &= ~ENC;                      // ADC10 disable
          ADC10CTL1 = INCH_0;
          ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10IE +  + ADC10ON ;

             ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start

             __bis_SR_register(CPUOFF + GIE);        // LPM0, ADC10_ISR will force exi
             ADC_Result = ADC10MEM;
             Byte1 = (char) (ADC_Result >> 8);
             Byte0 = (char) ADC_Result;
               while (!(IFG2 & UCA0TXIFG));
               UCA0TXBUF = Byte1 ;
               while (!(IFG2 & UCA0TXIFG));
               UCA0TXBUF = Byte0 ;
              Temp_Humidity_Switch=1;

      break;
      case 1:
      ADC10CTL0 &= ~ENC;                      // ADC10 disable
      ADC10CTL0 = SREF_1 + ADC10SHT_3 + REF2_5V + ADC10IE + REFON + ADC10ON;
      ADC10CTL1 = INCH_10 ;  // TA trig., rpt, A10

    ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start

    __bis_SR_register(CPUOFF + GIE);        // LPM0, ADC10_ISR will force exi
    ADC_Result = ADC10MEM;
    Byte1 = (char) (ADC_Result >> 8);
    Byte0 = (char) ADC_Result;
      while (!(IFG2 & UCA0TXIFG));
      UCA0TXBUF = Byte1 ;
      while (!(IFG2 & UCA0TXIFG));
      UCA0TXBUF = Byte0 ;
      while (!(IFG2 & UCA0TXIFG));
      UCA0TXBUF = 0xFF ;

      Temp_Humidity_Switch=0;

      break;
      }

  }
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
    b++;
  __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void ta0_isr(void)
{

  TACTL = 0;

  a++;
  LPM0_EXIT;                                // Exit LPM0 on return
}


  • Byte1 = (char) (ADC_Result >> 8);
    Byte0 = (char) ADC_Result;
    while (!(IFG2 & UCA0TXIFG));
    UCA0TXBUF = Byte1 ;
    while (!(IFG2 & UCA0TXIFG));
    UCA0TXBUF = Byte0 ;

    You might consider the case where the CPU clock rate is much faster than the UART peripheral baud rate. The method you use of polling on the UCA0TXIFG flag is susceptible to the case where the second while() statement exits because the UART hasn't had a chance to clear the flag yet from when the first byte is written in.

    Try adding a small delay before the 2nd while() statement and see if that helps your problem.

    Alternately, you could change your code to use a character queue and feed the UART using an ISR.

  • Thanks very much for your reply! I tried to add delay before the 2nd while, but there are still byte missing after a while...I am trying to feed UART using ISR now...

  • In your code, I notice that you are disabling the reference and switch between 2.5V and 1.5V reference on each case. This will require a reference settling time on each run. Just leave the reference enabled even if you don’t want to use it for this conversion.
    Also, your code always executes case 0, then case1, then case 0 etc. with the switch being the only statement in the while loop. You can as well remove the switch and the cases and just put your code into the while loop directly.

    However, the sequence you use for sending is correct. As soon as you write to TXBUF, TXIFG is cleared, and as soon as it gets set again , you can write to TXBUF. There is no need for a delay and I can’t see how you could lose bytes here.
    So I suspect the receiver of your data as the culprit. Maybe the bytes you miss are ‘0’ bytes and the receiver is unable to differentiate between “received a ‘0’ byte” and “received nothing”.
    it’s also possible that your baudrate settings are not perfect. (which MSP are you using?) and from time to time, they differ so much form the other side’s baudrate that a frame error is detected and the byte is lost.

  • Many many thanks for your reply and suggestion!

    I am using MSP430G2553 and I write a GUI based on java to receive the data... Will G2553 cause the problem?

    Thanks a lot!

  • Yunxi Guo said:
    Will G2553 cause the problem?

    The G2553 by itself is as reliable as any other MSP. I’m pretty sure the data goes out correctly. And with 9600Bd, you should be able to safely use the application UART of the LaunchPad for the serial connection. But you may try with 1200Bd just to be sure. I’d check the Java COM library twice and search the internet for bugs in it. We encountered a lot of bugs under Java when working with UDP on Windows and Linux. Here it worked, there it didn’t. I wouldn’t be surprised to see similar problems with other interfaces like the serial one.

  • Thanks you very much for your professional answer!

    Finally I choose to add a start byte, stop byte and encoding byte to setup a message. In this way, I won't read the wrong data.

    Thans again!

**Attention** This is a public forum