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 baud rate weirdness

Other Parts Discussed in Thread: MSP430F2272

Greetings,

I have successful used the MSP430 UARTS in several projects using an MSP430F2272.

Now I'm designing with a 2618 part, using IAR Kickstart.

I've set the MCLK to 12Mhz, SMCLK to 12/4 = 3 Mhz. This works - I measured it on a port pin. 

UART  is set up using:

UCA0CTL1 |= UCSSEL_3;  // SMCLK

UCA0BR0 = 0x38;

UCA0BR1 = 0x01;

UCAMCTL = 0x55;

What I see is a 1.6mS bit time, for approximately 625 baud rate.

It acts like the BRCLK is not seeing SMCLK and I haven't a clue why not.

Any hints or help would be appreciated.

 

  • I do not see anything weird about that. What did you expect?

    Try set UCAMCTL = 0x54; (or, any even number). I expect to see ~9600 b/s.

    Setting BIT0 of UCAMCTL will slow down baudrate by a factor of 16.

  • Thanks O_C_Y. 

    I used an on-line calculator that said stuff a 0x55 in the control register. 

    That, plus not having a full understanding of what UCOS does, caused my problems.

    You rule.

  • That on-line calculator must be for MSP430F1xx. You cannot use it for F2xx.

  • Live and learn - thanks to folks like you.

  • old_cow_yellow said:
    That on-line calculator must be for MSP430F1xx. You cannot use it for F2xx.

    Why?

    The calculation for the non-oversampling mode hasn't changed between USART and USCI modules.

    And for oversampling mode, you can just assume/enter 1/16 of teh real input clock frequency to get the proper results.

    I didn't work with the 2x devices, but my uart baudrate calculation code for the 1611 worked flawlessly on the 5438.

  • Jens-Michael Gross said:

    ... The calculation for the non-oversampling mode hasn't changed between USART and USCI modules. ...

    Correct, but the way MCTL register is implemented has changed.

    For example,

    3000000 / 9600 = 312.5

    Thus for both USAR and USCI, you set BR registers to 312 as the divider and tell the "modulator" to use the next higher divider in 4 out of each 8 consecutive bit periods. For USART, you set MCTL to 0x55 (4 bits of 1's evenly placed in 8 bits). But for USCI, you have to set MCTL=0x08, which will generate the desired modulation pattern 0x55.

    I was wrong to say "you cannot use...". You could even use an abacus if you use and interpret the result correctly. But most people cannot.

  • old_cow_yellow said:
    the way MCTL register is implemented has changed.

    Oh, yes, you're right. Instead of writing the pattern directly, you now just write the number of bits (shifted by 1, asthe LSB is the oversampling selector) and the modulator will automatically make an even distribution. So 0x55 is 4 bits set, so it becomes 0x08. It's actually the same mecanism as  alreeady implemented in the DCO modulation form the beginning.

    It makes the modulator calculation far easier, as you do not have to iteratively determine the positions of the bits and only need to calculate how many bits need to be set (which is a simple formula)

    I completely forgot that I had to change this part in my UART functions too :)

  • eltury,

    you can use the attached USCI Baudrate calculator for future calculation. I wrote this calc in JS and have been meaning to post it on the msp430 wiki but it doesn't like any javascript (probably for a good reason). But you should be able to open the html in your browser offline and use the tool.

    Link to package: http://e2e.ti.com/cfs-file.ashx/__key/CommunityServer-Discussions-Components-Files/166/5468.USCI_5F00_BaudRateCalculator.zip

     

    Link to thread with attached zip, in case direct file link doesn't work: 

    http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/p/74756/287087.aspx#287087

     

    Regards,

    Dung

  • Dung Dang said:
    you can use the attached USCI Baudrate calculator for future calculation.

    Or you put some small code into the program, so it will calculate the settings at runtime whenever you want to set the baudrate.

    Here's a code snipped which will configure the USCI based on requested baudrate and ACLK/SMCLK frequency
    ACLK and SMCLK are project-wide constants. ACLK being the smaller one (ACLK=1MHz, SMCLK=MCLK )

    I alread removed the funcitonality for using an uart parameter to select UART 0..3 and the setup for the send/receive ringbuffers
    If no automatic clock selection is needed, the code below can be simplified further

    void UartInit(unsigned long int baudrate){
      unsigned int divider;
        unsigned char mod, clocksource, oversampling;
    // calculate clock source, clock divider and modulation
      if(ACLK/baudrate>=48){                                                        // check for best clock source and oversampling options
        clocksource = 0;                                                            // ACLK is fast enough for oversampling
        oversampling = 1;
      }
      else if (SMCLK/baudrate>=48) {                                                // requires SMCLK for oversampling
        clocksource = 1;
        oversampling = 1;
      }
      else {                                                                        // no oversampling possible, SMCLK gives best result (should never happen)
        clocksource = 1;
        oversampling= 0;
      }
      divider=(((clocksource?SMCLK:ACLK)<<4)/baudrate);
      if(!oversampling) {
        mod = ((divider&0xF)+1)&0xE;                                                // UCBRSx (bit 1-3)
        divider >>=4;
      }
      else {
        mod = ((divider&0xf8)+0x8)&0xf0;                                            // UCBRFx (bit 4-7)
        divider>>=8;
      }
      UCA0CTL1 = UCSWRST;
      UCA0CTL1 |= clocksource?UCSSEL_SMCLK:UCSSEL_ACLK;        // set clock source (16MHz/1MHZ)
      UCA0CTL0 = 0;                                            // 8N1, LSB first, async. UART mode
      UCA0ABCTL = 0;                                           // auto baudrate disabled
      UCA0BR0 = divider;                                       // set divider low byte
      UCA0BR1 = divider>>8;                                    // set divider high byte
      UCA0MCTL = (oversampling?UCOS16:0)|mod;                  // set modulation
      UCA0CTL1 &= ~UCSWRST;                                    // release UART
      UCA0IE = UCRXIE;                                         // enable receive interrupt. Transmit interrupt remains disabled until there is something to send
    }

     

**Attention** This is a public forum