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 data got some error sometimes

Other Parts Discussed in Thread: MSP430F47177, MSP430F5418

I use UART 0 and 1 to receive much data on MSP430 F2416. It  worked perfect almost. But it corrupted sometime. Maybe lose one or two or three byte. Below list are my settings:

Crystal is 4 MHz for ACLK
baudrate on 4800 BPS:
UCA0BR0 = 0x34;
UCA0BR1 = 0x00;
UCA0MCTL = UCBRF_1 + UCBRS_0 + UCOS16;

baudrate on 115200 BPS:
UCA0BR0 = 0x02;
UCA0BR1 = 0x00;
UCA0MCTL = UCBRF_2 + UCBRS_3 + UCOS16;

It's very thanks for your help.

  • It seems that your settings are correct, according to the calculations in section 15.3.10 of the 2xx Users Guide.  What type of corruption are you viewing (missing data, corrupted data, shifted data)?  Can you give more details about the transmitter in your system? Is it another MSP?  

    Without the external transmitter, are you able to verify that the data is being transmitted correctly using the attached example?  In this example the TX is fed back to the Receiver using the UCLISTEN bit in the UCASTAT register.  If this is achieved, remove the internal TX/RX connection and use the external transmitter.  However, you should try sending a known value like 0x55.  This will allow you to see what is exactly happening to the received data.

  • It's missing data. I use GSM module to download text file from remote web server.  The data is received from UART 1. It seems like no data is missed to GSM and data is not missed on UART 1 almost. But it got somethings wrong sometimes.  

    ---------------------------------------------------------------

    data on web server:

    C8 00 3A 14 7B 3C 3D 40 0B 2F B0 13 42 58 19 20

    82 93 B6 14 12 38 1C 41 06 00 B0 13 B8 B8 1C 93

    08 20 92 41 06 00 90 14 B2 40 22 00 3A 14 80 00

    data on UART 1:

     

    C8 00 3A 14 7B 3C 3D 40 0B 2F B0 13 42 58 19 20

    82 93 B6 14 12 38 1C 41 06 00 B0 13 B8 B8 1C 93

    08 0 2 41 06 00 90 14 B2 40 22 00 3A 14 80 00

     

     

     

  • I also have similar problem of missing data in UART communication. I use MSP430F47717. I use USCIA0RX.

     

    I made a simple code only using UART module without any other heavy-loaded process. This simple code worked without problem for a long time

    (at least 10min).

    However, when I use the same UART code with somewhat heavy-loaded process (such as ADC ISR OSR128 * 4 channel * 30Hz), the UART

    module fails to pick up some of the data.

     

    Followings are sample data I should obtain throught the UART

    - $00003{CR}

    - !00{CR}

     Normally, I obtain above 2 lines. However, sometime I obtain 1line of $00003!00, or 2lines of

    $00003{CR} and !0{CR}, or  $00003{CR} and 00{CR}, or 00003{CR} and !00{CR} and other.

     

    I success when I use _DINT() before and _EINT() after the RX ISR. However, this make the ADC Hz smaller. So not so good way to solve this problem.

     

  • Hi,

    OKY, your problem seems to be different from what ALVIN seems to be having. ALVIN is getting errors in data, but getting the correct amount of data. However you seem to be missing data altogether. You mention that your code seems to be working fine when there is no heavy load. This means you may be missing UART interrupts. If you do not read UCA0RXBUF before the next one is written then you will miss an interrupt & a character. You can check if you have missed an interrupt with the UCOE flag in UCA0STAT register. In your UART RX ISR before reading UCA0RXBUF check this register and see if the UCOE flag is set. Please note that this flag will be reset on reading of UCA0RXBUF. Therefore read the flag before reading the UCA0RXBUF register. If the flag is set, it means you have lost an interrupt and a character.

    ALVIN can you check UCRXERR flag in UCA0STAT ? It will indicate if there are any errors is UART receptions.

    Regards,

    Praval

  • Thank you very much for your reply.

     

    I will check UCOE to see if there is some overrun errors.

    I appreciate your reply.

     

  • Hello, Praval.

    You're right. I got caught in the following _NOP() when I use UART with heavy-loaded process, but not caught with only UART process.

        if((UCA0STAT & UCOE) > 0) { // F2
            _NOP();   
        }

    Now I can concentrate on solving the over run errors for this problem.

     

    Best regards

     

  • Hi OKY,

    Are you using interrupts for UART data reception? You had mentioned that when you include ADC ISR in your code you start losing UART data. Depending on the UART baud rate you are using, you can calculate after how much time you will receive UART interrupt. You must ensure that your other ISR's do not run for more than that time or else you will lose the UART interrupt. This is because the GIE is bit is reset when you go into an ISR by default. This means your ISR is not interruptable by default. Therefore if you run your ISR for too long you will miss other interrupts. If you do have a time consuming ISR, you can look at enabling interrupts manually inside the ISR, if that is possible.

    Regards,

    Praval

  • Hi Praval Jain,

    I have checked the UCRXERR flag in UCA0STAT.  But no indication showed in UART error receptions.

    Thanks you

  • Hi ALVIN,

    Have you checked that the GSM module is not causing the error ? Can you connect the UART to a PC for example and see if the file dump is ok ?

    Regards,

    Praval

  • Thank you again for your useful comments.

    As you wrote, I checked my other ISRs by adding GIE. Then, the overrun did not happen.

    You're right. My ISRs was somewhat time consuming. And by enabling GIE inside ISR, I

    could solve this problem.

     

    Best regards

     

  •  


    Now I have similar trouble with ALVIN. When I try to incorporate GPS data through
    9600bps, sometime data got changed.

    Following is the result. The "50(D0)" and "56(D6)" mean that data monitored with
    line monitor between GPS and MSP430 got changed from 50 to D0 and from 56 to D6.
    So it seems that GPS outputs correct data, but incorporation by MSP430 fails.

    ----------------------
    24 47 50(D0) 52 4D 43
              
    2C 30 31 30 34 31

    36 2C 56(D6) 2C 33 34
        
    34 30 2E 31 31 36

    35 2C 4E 2C 31 33

    35 33 31 2E 38 36

    33 30 2C 45 2C 2C

    2C 31 38 30 32 31
    ----------------------

    When I try same things using 4800bps, the data did not change.

    As suggested before, I checked UCRXERR and UCOE. These errors actually occured.
    But not at exactly time when the data got changed "50(D0) and 56(D6) of above".

    Attached at the bottom is my code for this test.

    When I use 4800bps, the program goes directly to "break point 3" without change
    of the data.

    When I use 9600bps, sometimes, program goes directly to "break point 3",
    but with change of data in part. Or sometimes program goes to "break point 2" and
    "break point 1" but not at the time when the data got changed (I mean, at
    the time of [50] and [56] of above). So it seems that data change and (UCRXERR and
    UCOE) are somewhat different problem?


    Question:
    1. Are there any bottle neck in this code to capture 9600bps GPS data?
    2. Are there any improvement for 9600bps?

    ==============================================================================

    #include  <msp430x471x7.h> // msp430F47177
    #include <string.h>

    //#define DEBUG_UART4800 // uncomment for 4800bps

    /*

        GARMIN GPS15L-W (output data every second)
       
        ADM3222 (4UART device using 1 line)

    */

    #define UART_BUFF_SIZE 200
    unsigned char s_uartPcRdBuf[UART_BUFF_SIZE];
    unsigned char g_zBuf[20][UART_BUFF_SIZE];
    int idx=0;

    //------------- function prototype ------------------

    int main( void )
    {
        int i;
       
        WDTCTL = WDTPW + WDTHOLD;
        FLL_CTL0 |= XCAP14PF;                     
       
        do
        {
            IFG1 &= ~OFIFG;                         
            for (i = 0x47FF; i > 0; i--);           
        }
        while ((IFG1 & OFIFG));                   
       
        // For UART Switch (4 set using 1 line)
        P8DIR |= (BIT7 + BIT6 + BIT5 + BIT4 + BIT3 + BIT2 + BIT1 + BIT0);   

        P1SEL |= BIT6 + BIT7;                     
        UCA1CTL1 |= UCSSEL_1;                     // 32kHz
    #ifdef DEBUG_UART4800   
        UCA1BR0 = 0x06;                           // 4800bsp
        UCA1BR1 = 0x00;                           //
        UCA1MCTL |= UCBRS_7+UCBRF_0;              
    #else   
        UCA1BR0 = 0x03;                           // 9600bps
        UCA1BR1 = 0x00;                           
        UCA1MCTL = 0x06;   
    #endif       
        UCA1CTL1 &= ~UCSWRST;                     
        UC1IE |= UCA1RXIE;                          
                   
        // set ADM3222 Shutdown and Enable
        P8OUT |= (BIT1 + BIT3 + BIT5 + BIT6); // to use UART line connected with GPS

        __bis_SR_register(LPM3_bits + GIE);   
       
        return 0;

    }

    #pragma vector=USCIAB1RX_VECTOR
    __interrupt void USCIA1RX_ISR (void)
    {
        static int ridx=0;
        unsigned char zbuf;

        _NOP();
           
        if((UCA1STAT & UCOE) > 0) {
            _NOP();     // break point1
        }   
       
        if((UCA1STAT & UCRXERR) > 0) {
            _NOP();     // break point2
        }     
     
        zbuf = UCA1RXBUF;

        if (ridx < sizeof(s_uartPcRdBuf) - 1) {
            if (zbuf == '\r') {
                if(ridx > 0) {
                    strcpy((char *)g_zBuf[idx++], (char *)s_uartPcRdBuf);
                                   
                    if(idx == 16) {
                        _NOP(); // break point 3
                    }
                    memcpy(s_uartPcRdBuf, 0, UART_BUFF_SIZE);
                }
                s_uartPcRdBuf[ridx] = '\0';
                ridx = 0;
            } else if (zbuf >= ' ') {
                s_uartPcRdBuf[ridx++] = zbuf;
                if(ridx >= UART_BUFF_SIZE) {    // avoid overFlow
                    ridx = UART_BUFF_SIZE - 1;
                }
            }
        } else {
            ridx = 0; // to avoid overflow
        }
       
    }

     

     

  • Hi OKY,

    Have you looked at Table 19-4 in the User Guide ? While your settings for baud rate generation from 32768Hz crystal seem to be ok, the table mentions worst case errors based on that settings. If you look at 9600bps for 32768, then there is a -44.3% Max RX error. The values for 4800bps are much smaller.

    If you read the description:

    "The receive error is the accumulated time versus the ideal scanning time in the middle of each bit."

    This actually means in worst case you may be 44.3% off the ideal scanning time while receiving data. From this it seems that there might be intermittent errors if 9600bps is used generated from a 32768Hz crystal. If you see lower down in the table you will notice much lesser error values if you use a higher clock frequency. You might want to use a higher clock frequency if you want to use 9600bps.

    Regards,

    Praval

  • Thank you for your reply, Praval.

     

    According to your suggestion, I modified to use DCO (1,048,576Hz) as follows. Then, the program

    can obtain all the data without change.

        UCA1CTL1 |= UCSSEL_2;                     // 1,048,576Hz
        UCA1BR0 = 109;                           // 9600bps
        UCA1BR1 = 0x00;                           
        UCA1MCTL = UCBRS_2 + UCBRF_0;       

     

    I will read more on the setting of these clocks for further study.

     

    I appreciate your reply.

     

     

  • Hi Praval Jain,

    I feel sorry too late to reply cause Chinese new year vacation.

    Yes. I always connected the UART to PC to checked the file dump. It's not loss data in RS232 terminal.

    But if  I sent RXBUF1 to TXBUF0 in UART1 RXD ISR to check (Data was received from RXBUF1), I'll found data was missed.

    You suggested OKY to read UART settings to reduce receive error. Is my problem same to OKY ?

     

  • Hi ALVIN,

    My suggestion to OKY was based on the fact that he was using a very low frequency crystal (32768Hz) for generation of  9600bps baud rate. Using such a low frequency crystal may lead to a sampling time mismatch in the worst case due to which there may be receive errors.  In your case the crystal you are using is of 4MHz (more than 100 times higher) and the setting you are using lead to very low worst case error. Hence the chances of errors in reception should be almost nil.

    One possibility could be that the crystal you are using is not giving the exact frequency for which we have done the baud rate calculations. This is quite possible if the loading of the crystal is not proper. So instead of 4MHz you could be getting 4.1 MHz or 3.9 MHz for example, which may lead to some UART errors. Can you shift from this external crystal and use the internal DCO instead using the factory calibrated settings ? The DCO factory settings are for 1MHz & 8MHz and so on. What you can do is use the DCO factory setting(stored in the Info memory) for 8MHz and then use indivindual dividers for MCLK, SMCLK & ACLK to move from 8MHz to 4MHz. Therefore effectively there is no change in any of your code, you just need to modify the clock registers to use the internal DCO for clock generation rather than the external crystal. You can try this out and see if you still get errors.

    Regards,

    Praval

  • I'm encountering something weird.

    Firstly. I am using a MSP430F5418. Clock is 32768Hz. DCO at 4MHz.

    I too am encountering overrun problem.

    I have a PC program which is constantly sending a string of data to my MCU.

    However, strangely, the overrun problem only occurs when I am using the DCO as clock input. Using ACLK as clock input the overrun error didn't occur.

    When it happens, the framing error flag is also set.

    The difference between the 2 is only a difference in setting the baud rate and selecting the input clock.

    Is there something wrong in the setting that could cause this problem?

  • What do you mean with 'DCO as clock input' vs- 'ACLK as clock input'?

    DCO is an oscillator source, ACLK is a system clock source. The USCI module does not accept direct oscillator sources. You can only select ACLK or SMCLK (or external), so this whole statement makes no sense to me.

    Do you mean that the problem occurs if you use DCO as oscillator source for ACLK, but not if you use 32768kHz clock as oscillator source to ACLK?

    Framign error is something different than overrun. It happens if your timing is so off that the UART detects a wrong (low) stopbit (or the data has been corrupted on teh line, which may happen due to noise but isn't likely). This might be because the start of the next character is counted erroneously as the rest of the previous one. In this case the next character isn't received properly. Also, if UCRXEIE is not set, a framing error results in the received byte being discarded and NOT written into UCAxRXBUF. I don't know why an overrun is also flagged.

    It is possible that your DCO frequency is off. Remember that the DCO has a really high frequency tolerance as well as a high temperature coefficient. It is only a reliable clock source for UART timing if used with a properly set up FLL based on the 32kHz REFO. Because the calibrated REFO is available, the 54xx series does not have calibration values for the DCO.

    It's a good idea to use the 16x oversampling feature as it greatly enhances the detection accuracy if you do not have a 100% exact clock source. With a DCO of 16MHz (FFL stabilized) I have no problems with 115200Bd using oversampling. Having 1MHz clock and no oversampling, the errors are waaay off the tolerable range (16% maximum RX error). Actually, the 32kHz clock isn't suitable for any baudrate above 300Bd, so I wonder why you don't see any errors there

    Keep in mind that the sending baudrate of your data source might be a bit off too.

**Attention** This is a public forum