MSP430 Generación de velocidad en baudios: discrepancia en la hoja de datos

Mi proyecto se basa en el MSP430F5529. De la guía del usuario de la familia MSP430x5xx :

NOTA: Configuración rápida de la velocidad de transmisión

Para calcular la configuración correcta para la generación de velocidad en baudios, realice estos pasos:

  1. Calcule N = fBRCLK/velocidad en baudios [si N > 16 continúe con el paso 3, de lo contrario con el paso 2]

  2. OS16 = 0, UCBRx = INT(N) [continúe con el paso 4]

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

  4. UCBRSx se puede encontrar buscando la parte fraccionaria de N ( = N - INT(N) ) en la tabla Tabla 39-4

  5. Si se eligió OS16 = 0, TI recomienda realizar un cálculo de error detallado.

Actualmente estoy calculando la configuración de registro para 230,4 kbps con un reloj de 16 MHz. Mis calculos son los siguientes:

  1. N = (16000000/230400) = 69,4444 ....
  2. N / A
  3. OS16 = 1 (modo de sobremuestreo), UCBRx = (int)(69.4444/16) = 4 , UCBRFx = (int)([(69.4444/16)-(int)(69.4444/16)]*16) = 5
  4. Según la Tabla 39-4 (a continuación), N-(int)N = 69,4444-69 = 0,4444 => UCBRSx = 0x55

ingrese la descripción de la imagen aquí

Ahora aquí está la parte confusa. Si consulta la Tabla 36-5 en la página 954, verá las siguientes configuraciones recomendadas para 16 MHz a 230,4 kbps con OS16 = 1:

ingrese la descripción de la imagen aquí

Tenga en cuenta que se sugiere "5" para UCBRSx y "3" para UCBRFx. Como puede ver, estos números claramente no coinciden con los cálculos. Cuando uso los valores calculados y el valor para UCBRSx de la tabla de búsqueda, el UART no siempre se comporta correctamente, especialmente en las tasas de bits bajas (<9600 bps) y las altas (>115200 bps). Necesito poder calcular los valores de registro del generador de velocidad en baudios sobre la marcha de 300 bps a 230400 bps, y esta discrepancia en la hoja de datos lo hace muy difícil.

Si no puedo confiar en los cálculos, ¿cuál es la forma correcta de determinar los valores de registro? ¿Quizás estoy malinterpretando esto? También usé esta herramienta para calcular la configuración y los resultados coinciden con la Tabla 36-5 en la hoja de datos, aunque los cálculos mencionados en la página arrojan los resultados que obtuve de mis propios cálculos.

Veo que sugieren hacer un cálculo de error detallado para diferentes opciones, pero eso es en referencia a la configuración de velocidad de transmisión de baja frecuencia (OS16 = 0) o si se seleccionan valores solo entre 0 y 7 para UCBRSx. Esto parece ser diferente de la Tabla 39-4, ya que la tabla sugiere que se podrían usar valores entre 0x00 y 0xFF.

Mi código es el siguiente:

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;
}

Y la "tabla de búsqueda" (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;
}
No está calculando UCBRx correctamente. Olvidaste dividirlo por 16
¿Qué chip estás usando?
@EugeneSh. Lo siento, olvidé poner eso. Estoy calculando N=69.4444, pero estoy dividiendo por 16 para obtener el UCBRx (que es igual a 4 en este caso)
@jsolarski Actualizaré la publicación.
Supongo que la clave está en la oración final de 39.3.10.2: La configuración de la segunda etapa de modulación (UCBRSx) se puede encontrar realizando un cálculo de error detallado o usando la Tabla 39-4 y la parte fraccionaria de N = fBRCLK/velocidad en baudios. . Probablemente los valores de las tablas se obtengan utilizando un cálculo de error detallado .
@EugeneSh. Me preguntaba si ese era el caso. Es posible que deba renunciar a los cálculos por completo y armar una tabla de búsqueda completa para todos los valores que necesito (300 bps a 230400 bps).
Por extraño que parezca, los valores de la tabla no funcionan en 230400. Sospecho que mi reloj puede no ser exactamente 16 MHz, pero quizás 15999000 o algo así. No estoy seguro de qué tipo de tolerancia tiene este reloj, sin profundizar en la hoja de datos

Respuestas (2)

IIRC USCI y eUSCI son dos implementaciones de módulos de hardware diferentes (tenga en cuenta el apodo "mejorado" en la sección 39, nada en la sección 36).

Los manuales de referencia de TI tienden a incluir secciones para familias enteras, por lo que debe ir a la hoja de datos en particular para ver lo que realmente tiene.

El '5529 tendría la sección 36 según corresponda, no la sección 39, ya que no veo ninguna referencia a un eUSCI en la hoja de datos del dispositivo.

Estoy de acuerdo, también, que la tabla 36-4 y la tabla 36-5 deberían ser las configuraciones correctas.
Buena captura en eUSCI vs. USCI. No es la primera vez que me muerde eso. Parece que la tabla a la que me referí (39-4) NO es aplicable a mi situación, ya que estoy usando el UART no "mejorado". Parece que no tengo otra opción y tendré que realizar un análisis de error completo en la configuración de UCBRSx (0-7) para encontrar el que funcione correctamente. Probablemente terminaré construyendo una tabla de búsqueda para los valores.
Usaría una tabla de búsqueda y luego la actualizaría al segmento A si no usa la calibración DCO, si usa la calibración DCO o cualquier otra calibración que use el segmento A, el segmento B también funcionará, pero está limitado a 128 bytes también lo es C y D
Creo que me voy a imponer la restricción de que mi frecuencia de reloj siempre será de 16 MHz, en cuyo caso solo puedo usar un interruptor/caja para la tasa de baudios y aplicar valores determinados previamente. Creo que esto sería más rápido que una lectura desde flash

¿Cómo se compara esto? 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 

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

esta licencia de programa está en: http://www.fsf.org/licenses/licenses.html#GPL

  this program is distributed WITHOUT ANY WARRANTY

Usted entenderá si esto es relevante, no yo...

Incorporando los cambios contenidos en el parche entregado en mspgcc-20120911 https://github.com/contiki-os/contiki/wiki/MSP430X

Esa es una buena herramienta.