1
\$\begingroup\$

My project is based around the MSP430F5529. From the MSP430x5xx family user guide:

NOTE: Baud-rate settings quick set up

To calculate the correct the correct settings for the baud-rate generation, perform these steps:

  1. Calculate N = fBRCLK/baud rate [if N > 16 continue with step 3, otherwise with step 2]

  2. OS16 = 0, UCBRx = INT(N) [continue with step 4]

  3. OS16 = 1, UCBRx = INT(N/16), UCBRFx = INT([(N/16) – INT(N/16)] × 16)

  4. UCBRSx can be found by looking up the fractional part of N ( = N - INT(N) ) in table Table 39-4

  5. If OS16 = 0 was chosen, TI recommends performing a detailed error calculation.

I am currently calculating the register settings for 230.4 kbps with a 16 MHz clock. My calculations are as follows:

  1. N = (16000000/230400) = 69.4444....
  2. N/A
  3. OS16 = 1 (oversampling mode), UCBRx = (int)(69.4444/16) = 4, UCBRFx = (int)([(69.4444/16)-(int)(69.4444/16)]*16) = 5
  4. According to Table 39-4 (below), N-(int)N = 69.4444-69 = 0.4444 => UCBRSx = 0x55

enter image description here

Now here's the confusing part. If you refer to Table 36-5 on Page 954, you'll see the following recommended settings for 16 MHz at 230.4 kbps with OS16 = 1:

enter image description here

Note the "5" is suggested for UCBRSx and "3" is suggested for UCBRFx. As you can see, these numbers clearly do not match the calculations. When I use the calculated values and the value for UCBRSx from the lookup table, the UART does not always behave properly, especially at the low bit rates (<9600 bps) and the high ones (>115200 bps). I need to be able to calculate the baud rate generator register values on the fly for 300 bps to 230400 bps, and this discrepancy in the datasheet is making this very difficult.

If I can't trust the calculations, what is the correct way to determine the register values? Perhaps I am misinterpreting this? I have also used this tool to calculate the settings and the results match Table 36-5 in the datasheet, though the calculations mentioned on the page yield the results I got from my own calculations.

I do see that they suggest making a detailed error calculation for different options, but that is in reference either to the low-frequency baud rate setting (OS16 = 0) or if values only between 0 and 7 are selected for UCBRSx. This seems to be different from Table 39-4, as the table suggests that values between 0x00 and 0xFF could be used.

My code is as follows:

void uartConfig(uint32_t frequency, uint32_t baud) {

    float divFactor;
    uint16_t UCBRx;
    uint8_t oversampling;
    uint8_t UCBRFx;
    uint8_t UCBRSx;

    // Calculate baud rate modulation register values
    divFactor = (float)((float)frequency/(float)baud);
    // High frequency mode
    oversampling = USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;    // High frequency baud rate generation
    UCBRx = (uint16_t)(divFactor/16);                               // Calculate integer part of N divided by 16
    UCBRFx = round(((divFactor/16) - (uint16_t)(divFactor/16)) * 16);   // Calculate first modulation stage
    // Found from table for N-INT(N); See slau208q Pg. 1037 for details
    UCBRSx = getUCBRSxValue(divFactor);                             // Second modulation register

    uartParams.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK;
    uartParams.clockPrescalar = UCBRx;
    uartParams.firstModReg = UCBRFx;
    uartParams.secondModReg = UCBRSx;
    uartParams.parity = USCI_A_UART_NO_PARITY;
    uartParams.msborLsbFirst = USCI_A_UART_LSB_FIRST;
    uartParams.numberofStopBits = USCI_A_UART_ONE_STOP_BIT;
    uartParams.uartMode = USCI_A_UART_MODE;
    uartParams.overSampling = oversampling;
}

And the "lookup table" (ish):

// Lookup table for UCBRSx values
uint8_t getUCBRSxValue(float factor) {
    uint16_t frac = (factor - (uint16_t)factor) * 10000;
    if (frac < 529) {
        return 0x00;
    } else if ((frac >= 529) && (frac < 715)) {
        return 0x01;
    } else if ((frac >= 715) && (frac < 835)) {
        return 0x02;
    } else if ((frac >= 835) && (frac < 1001)) {
        return 0x04;
    } else if ((frac >= 1001) && (frac < 1252)) {
        return 0x08;
    } else if ((frac >= 1252) && (frac < 1430)) {
        return 0x10;
    } else if ((frac >= 1430) && (frac < 1670)) {
        return 0x20;
    } else if ((frac >= 1670) && (frac < 2147)) {
        return 0x11;
    } else if ((frac >= 2147) && (frac < 2224)) {
        return 0x21;
    } else if ((frac >= 2224) && (frac < 2503)) {
        return 0x22;
    } else if ((frac >= 2503) && (frac < 3000)) {
        return 0x44;
    } else if ((frac >= 3000) && (frac < 3335)) {
        return 0x25;
    } else if ((frac >= 3335) && (frac < 3575)) {
        return 0x49;
    } else if ((frac >= 3575) && (frac < 3753)) {
        return 0x4A;
    } else if ((frac >= 3753) && (frac < 4003)) {
        return 0x52;
    } else if ((frac >= 4003) && (frac < 4286)) {
        return 0x92;
    } else if ((frac >= 4286) && (frac < 4378)) {
        return 0x53;
    } else if ((frac >= 4378) && (frac < 5002)) {
        return 0x55;
    } else if ((frac >= 5002) && (frac < 5715)) {
        return 0xAA;
    } else if ((frac >= 5715) && (frac < 6003)) {
        return 0x6B;
    } else if ((frac >= 6003) && (frac < 6254)) {
        return 0xAD;
    } else if ((frac >= 6254) && (frac < 6432)) {
        return 0xB5;
    } else if ((frac >= 6432) && (frac < 6667)) {
        return 0xB6;
    } else if ((frac >= 6667) && (frac < 7001)) {
        return 0xD6;
    } else if ((frac >= 7001) && (frac < 7147)) {
        return 0xB7;
    } else if ((frac >= 7147) && (frac < 7503)) {
        return 0xBB;
    } else if ((frac >= 7503) && (frac < 7861)) {
        return 0xDD;
    } else if ((frac >= 7861) && (frac < 8004)) {
        return 0xED;
    } else if ((frac >= 8004) && (frac < 8333)) {
        return 0xEE;
    } else if ((frac >= 8333) && (frac < 8464)) {
        return 0xBF;
    } else if ((frac >= 8464) && (frac < 8572)) {
        return 0xDF;
    } else if ((frac >= 8572) && (frac < 8751)) {
        return 0xEF;
    } else if ((frac >= 8751) && (frac < 9004)) {
        return 0xF7;
    } else if ((frac >= 9004) && (frac < 9170)) {
        return 0xFB;
    } else if ((frac >= 9170) && (frac < 9288)) {
        return 0xFD;
    } else if (frac >= 9288) {
        return 0xFE;
    }
    return 0x00;
}
\$\endgroup\$
  • \$\begingroup\$ You are not calculating UCBRx correctly. You forgot to divide it by 16 \$\endgroup\$ – Eugene Sh. Dec 7 '18 at 17:05
  • \$\begingroup\$ What chip are you using? \$\endgroup\$ – jsolarski Dec 7 '18 at 17:05
  • \$\begingroup\$ @EugeneSh. Sorry, I forgot to put that in. I am calculating N=69.4444, but I am dividing by 16 in order to get the UCBRx (which is equal to 4 in this case) \$\endgroup\$ – DerStrom8 Dec 7 '18 at 17:07
  • \$\begingroup\$ @jsolarski I will update the post. \$\endgroup\$ – DerStrom8 Dec 7 '18 at 17:07
  • 1
    \$\begingroup\$ I guess the key is in the final sentence of 39.3.10.2: The second modulation stage setting (UCBRSx) can be found by performing a detailed error calculation or by using Table 39-4 and the fractional part of N = fBRCLK/baud rate.. Probably the values from the tables are obtained using detailed error calculation. \$\endgroup\$ – Eugene Sh. Dec 7 '18 at 17:11
1
\$\begingroup\$

IIRC USCI and eUSCI are two different hardware module implementations, (note the "enhanced" moniker in section 39, nothing in section 36).

The TI reference manuals tend to throw in sections for entire families, so you have to go to the particular datasheet to see what you actually have.

The '5529 would have section 36 as applicable, not section 39, as I don't see any references to an eUSCI on the device datasheet.

\$\endgroup\$
  • \$\begingroup\$ I agree, as well, table 36-4 and table 36-5 should be the correct settings. \$\endgroup\$ – jsolarski Dec 7 '18 at 17:40
  • \$\begingroup\$ Good catch on the eUSCI vs. USCI. That's not the first time I've been bitten by that. It seems that table I referred to (39-4) is indeed NOT applicable to my situation, as I am using the non-"enhanced" UART. It seems that I do not have a choice and will need to perform a full error analysis on the UCBRSx settings (0-7) to find the one that works correctly. I will probably end up just building a lookup table for the values. \$\endgroup\$ – DerStrom8 Dec 7 '18 at 18:22
  • \$\begingroup\$ I would use a look up table then custom flash it to segment A if you do not use DCO calibration, if you do use DCO calibration or any other calibration that uses segment A, segment B will work as well, but it is limited to 128bytes as well is C and D \$\endgroup\$ – jsolarski Dec 7 '18 at 18:54
  • \$\begingroup\$ I think I'm going to impose on myself the restriction that my clock frequency will always be 16 MHz, in which case I can just use a switch/case for the baud rate and apply previously-determined values. I think this would be faster than a read from flash \$\endgroup\$ – DerStrom8 Dec 7 '18 at 19:22
1
\$\begingroup\$

How does this compare? UCA0MCTL = 0x5B

clock: 16000000Hz
  desired baud rate: 230400bps
  division factor: 69.5
  effective baud rate: 230216bps
  maximum error: 0.0347us   0.80%

  time table (microseconds):
        event      desired effective  error   error%
startbit->D0      4.34      4.31  +0.0277  +0.64
D0->D1            8.68      8.69  -0.0069  -0.16
D1->D2           13.02     13.00  +0.0208  +0.48
D2->D3           17.36     17.38  -0.0138  -0.32
D3->D4           21.70     21.69  +0.0138  +0.32
D4->D5           26.04     26.06  -0.0208  -0.48
D5->D6           30.38     30.37  +0.0069  +0.16
D6->D7           34.72     34.75  -0.0277  -0.64
D7->stopbit      39.06     39.06  +0       +0.00
end of stopb     43.40     43.44  -0.0347  -0.80

 UBR00=0x45; UBR10=0x00; UMCTL0=0xAA;  uart0 16000000Hz 230215bps 
 UBR01=0x45; UBR11=0x00; UMCTL1=0xAA;  uart1 16000000Hz 230215bps 

uart calculator: http://mspgcc.sourceforge.net/baudrate.html

this program license is at: http://www.fsf.org/licenses/licenses.html#GPL

  this program is distributed WITHOUT ANY WARRANTY

You will understand if this is relevant, not I...

Incorporating the changes contained in the patch delivered in mspgcc-20120911 https://github.com/contiki-os/contiki/wiki/MSP430X

\$\endgroup\$
  • \$\begingroup\$ That is a nice tool. \$\endgroup\$ – jsolarski Dec 7 '18 at 17:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.