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.

MSP430FR2355: UART not working above 19200??

Part Number: MSP430FR2355


Good afternoon...

I am using an MSP430FR2355 development board connected to a PC.  Using RealTerm on the PC side...

I can set the baud rate to 19200 and 9600 and all works fine but if I set it above 19200 I am getting the wrong characters.  I have verified the following registers are set per the  user guide at multiple baud rates above 19.2.  for instance

1.  smclk 8mhz (verified on P1.0), also verified SMCLK is being used within UART control register setting

2. verified also against table 22.5 of user manual settings :  UCOS16, UCBR, UCBRF, UCBRS...

3.  verified RealTerm is set up to correct baud.

A breakpoint at the beginning of the ISR verifies right at the front end of the ISR that RXBUFFER is erroneous which makes me think there is something missing in the setup??

Does anyone have any ideas as to what I may be missing or something to try as I am all out of ideas as to why I cannot go faster?  (the code (in main) does nothing except LPM3 (I see no improvement in LPM0).  It waits for UART characters to come in then acts.

The ISR is quite simple (with a timeout armed inside it in case characters stop)

      case USCI_UART_UCRXIFG:
          buffer[mssgLength] = UCA1RXBUF;
          mssgLength++;
          if (monitor == 0)
              TimerCC_Delay(TIMER0, CC_ZERO, ONE_SECOND);

          monitor = 1;
          if (UCA1RXBUF == 0x0D)
          {
              mssgLength--;
              ISR.UARTmssgRcvdFlag = T;
              LPM3_EXIT;
          }
          break;

thanks

  • Hi Steve,

    According to the MSP Debuggers document, there are limits to the baud rates the ezFET can support. Please note there are the only support frequencies.  Excerpt below:

    Regards,

    Evan

  • Not convinced.....I took the jumpers off of SBWTDIO and SBWTCK to make Debugger inactive ...mclk at 16mhz, divide by 2 for smclk...baud set to 115200...registers all look fine....still a no go...then tried 38400, once again registers look good....

    I loaded code verified register settings then stopped running debugger, disconnected jumpers powered down target and repowered and doesn't work???

  • I see no RXBUFFER in the code posted. I worry about that ISR. After receiving a full line you wake up the main program but the ISR is still operating which could cause trouble with the buffer.

    I could point you to an example that I routinely run at 38400 (I haven't tried any higher) but it is in assembly. I use FIFO queues for the data.

  • RXBUFFER (sorry my bad)....this is just indicating the buffer....if you look at ISR you will see the correct assignment ie UCA1RXBUF....

    I have used this concept successfully....that is the first line in main after wakeup is 

            if (ISR.UARTmssgRcvdFlag)
            {
                applicationUART.pSysCommsA->UCAxIE &= ~UCRXIE;
    

  • I am using the external 32khz crystal...

    Can you comment on REFOLP bit setting and DISMOD bit setting.....I have tried flipping these to REFOLP = 0 (ie high power) but to no avail....I saw I had some code (somewhat different due to the nature of the project) that works at a higher baud but it had DISMOD =1 which looks wrong to me....in this project I have DISMOD = 0?? (these are in the CS section)

  • So I scaled the application down to bare bones....I am finding that at 38400 the first byte of information received is corrupt ....So I changed to LPM0 and they all come in at 38400....I then move to 115200 and I see that at LPM0 the first byte is again bad....It looks like the processor can't wake up in time or something???  

    My clock is 8MHz and the debugger is connected which according to Evan's picture above should work....I'd really like to operate this at LPM3....can I not do this....My SMCLKREQEN is set....seems I should wake up 

  • I would like to hear someone from TI comment on this please??  Seems impossible to get >19.2Kbaud on Receive wakeup from LPM3 

    I have looked and the datasheet says that typical wake up time from LPM3 is 10us.....115.2kbaud is 8.7us, so I have to believe it is impossible to wake up on UART RX interrupt and successfully work at 115200 baud rate.  I have not been able to wake up from UART RX using LPM3 and capture all the incoming characters on anything greater than 19.2kBaud...If I go to LPM0 I can get 38400....

    Here is some basic code at 38400 (I stripped out all libraries and moved UART and clk inits to within the file just in case it was branching that was causing grief), LPM3 that erroneously brings in the 1st character....

    #include "main.h"
    
    void init_ClockTo16MHz(void);
    static void Software_Trim();
    void UART_Init(void);
    uint16_t itoa(uint16_t k);
    
    struct HardFlags ISR = {F};
    
    static __vo uint8_t buffer[MSSG_LENGTH] = { [ 0 ... MSSG_LENGTH - 1] = 0 }, monitor = 0;
    
    __vo uint8_t mssgLength = 0;
    
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
        PM5CTL0 &= ~LOCKLPM5;
        init_ClockTo16MHz();
        UART_Init();
    
    
    
        while(1)
        {
            __bis_SR_register( LPM3_bits + GIE);
    
            if (ISR.UARTmssgRcvdFlag)
            {
                UCA1IE &= ~UCRXIE;
                ISR.UARTmssgRcvdFlag = F;
                mssgLength = 0;
                UCA1IFG &= ~UCRXIFG;
                UCA1IE |= UCRXIE;
            }
    
        }
    }
    
    #pragma vector=USCI_A1_VECTOR
    __interrupt void COMM_ISR(void)
    {
        switch(__even_in_range(UCA1IV, USCI_UART_UCTXCPTIFG))
        {
          case USCI_NONE: break;
          case USCI_UART_UCRXIFG:
              buffer[mssgLength] = UCA1RXBUF;
    
    
              if (buffer[mssgLength] == 0x0D)
              {
                  ISR.UARTmssgRcvdFlag = T;
                  LPM3_EXIT;
              }
    
              mssgLength++;
              break;
          case USCI_UART_UCTXIFG:
              break;
          case USCI_UART_UCSTTIFG: break;
          case USCI_UART_UCTXCPTIFG: break;
        }
    }
    
    #ifdef LOCAL
    void UART_Init(void)
    {
        P4SEL0 |= BIT3 | BIT2;
        UCA1CTLW0 |= UCSWRST;
        UCA1CTLW0 |= UCSSEL__SMCLK;
        //UCA1BR0 = 52; //19200
        UCA1BR0 = 13; //115200
        UCA1BR1 = 0x00;
        //UCA1MCTLW = 0x4900 | UCOS16 | UCBRF_1; //19200
        UCA1MCTLW = 0x8400 | UCOS16 | UCBRF_0; //115200
        UCA1CTLW0 &= ~UCSWRST;
    
        UCA1IFG &= ~UCRXIFG;
        UCA1IE |= UCRXIE;
    
    }
    
    
    void init_ClockTo16MHz(void)
    {
        FRCTL0 = FRCTLPW | NWAITS_1;
        P2SEL1 |= BIT6 | BIT7;
        do
        {
            CSCTL7 &= ~(XT1OFFG | DCOFFG);           // Clear XT1 and DCO fault flag
            SFRIFG1 &= ~OFIFG;
        } while (SFRIFG1 & OFIFG);                   // Test oscillator fault flag
    
        __bis_SR_register(SCG0);                     // disable FLL
        CSCTL3 |= SELREF__XT1CLK;                    // Set XT1 as FLL reference source
        CSCTL1 |= DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_5;// DCOFTRIM=5, DCO Range = 16MHz
        CSCTL2 = FLLD_0 + 487;                       // DCOCLKDIV = 16MHz
        __delay_cycles(3);
        __bic_SR_register(SCG0);                     // enable FLL
        Software_Trim();
        while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));
        CSCTL5 |= DIVS_1;
        CSCTL4 = SELMS__DCOCLKDIV | SELA__XT1CLK;   // set XT1 (~32768Hz) as ACLK source, ACLK = 32768Hz
    }
    
    
    static void Software_Trim()
    {
        unsigned int oldDcoTap = 0xffff;
        unsigned int newDcoTap = 0xffff;
        unsigned int newDcoDelta = 0xffff;
        unsigned int bestDcoDelta = 0xffff;
        unsigned int csCtl0Copy = 0;
        unsigned int csCtl1Copy = 0;
        unsigned int csCtl0Read = 0;
        unsigned int csCtl1Read = 0;
        unsigned int dcoFreqTrim = 3;
        unsigned char endLoop = 0;
    
        do
        {
            CSCTL0 = 0x100;                         // DCO Tap = 256
            do
            {
                CSCTL7 &= ~DCOFFG;                  // Clear DCO fault flag
            }while (CSCTL7 & DCOFFG);               // Test DCO fault flag
    
            __delay_cycles((unsigned int)3000 * 16);// Wait FLL lock status (FLLUNLOCK) to be stable
                                                               // Suggest to wait 24 cycles of divided FLL reference clock
            while((CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)) && ((CSCTL7 & DCOFFG) == 0));
    
            csCtl0Read = CSCTL0;                   // Read CSCTL0
            csCtl1Read = CSCTL1;                   // Read CSCTL1
    
            oldDcoTap = newDcoTap;                 // Record DCOTAP value of last time
            newDcoTap = csCtl0Read & 0x01ff;       // Get DCOTAP value of this time
            dcoFreqTrim = (csCtl1Read & 0x0070)>>4;// Get DCOFTRIM value
    
            if(newDcoTap < 256)                    // DCOTAP < 256
            {
                newDcoDelta = 256 - newDcoTap;     // Delta value between DCPTAP and 256
                if((oldDcoTap != 0xffff) && (oldDcoTap >= 256)) // DCOTAP cross 256
                    endLoop = 1;                   // Stop while loop
                else
                {
                    dcoFreqTrim--;
                    CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4);
                }
            }
            else                                   // DCOTAP >= 256
            {
                newDcoDelta = newDcoTap - 256;     // Delta value between DCPTAP and 256
                if(oldDcoTap < 256)                // DCOTAP cross 256
                    endLoop = 1;                   // Stop while loop
                else
                {
                    dcoFreqTrim++;
                    CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4);
                }
            }
    
            if(newDcoDelta < bestDcoDelta)         // Record DCOTAP closest to 256
            {
                csCtl0Copy = csCtl0Read;
                csCtl1Copy = csCtl1Read;
                bestDcoDelta = newDcoDelta;
            }
    
        }while(endLoop == 0);                      // Poll until endLoop == 1
    
        CSCTL0 = csCtl0Copy;                       // Reload locked DCOTAP
        CSCTL1 = csCtl1Copy;                       // Reload locked DCOFTRIM
        while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked
    }
    #endif
    

  • The data sheet has a table (5-2) which tells you how much time it takes to wake up. Wakeup time from LPM3 is 10us.

    While the UART has the ability to wake up, it does that on the falling edge of the start bit. If the clock isn't running, timing is going to be a problem because everything is referenced to that falling edge. Or when the clock starts, whichever comes last.

  • Hi David...

    Yes that is where I am at...I don't think it can be done....although doesn't it seem like it could do 57.6kBaud?

  • Although difficult to understand the user guide seems to suggest sampling in the middle of the bit....so maybe 57.6 is out also.....but it does seem 38.4 would be possible at LPM3?  You mentioned you did it in assembly but with FIFOs??  I don't know assembly but.......I did post my code above at 38.4 that does NOT work....any thoughts?

  • My example doesn't use a low power mode most of the time. I have run it using one and don't recall any trouble. I mention the assembly part as that tends to scare off many C programmers. There is really nothing in it that couldn't be done in C but the project had to be in assembly.

    At 38,400 bps a 10us delay puts you close to the center of the bit. Even assuming that the start bit is detected, all subsequent bits are going to have that same skew. Assuming that the modulator is in use (it would have to be with a 8MHz reference clock), then you have to add those errors as well. So 38,400 would be problematic because the sampling times would be so close to the edge of the bit.

    If you must use LPM3 and higher bit rates, you are going to have to find a way to start the clock before the data arrives. Then keeping it active until all of the data is received.

**Attention** This is a public forum