Cómo configurar la velocidad en baudios para la comunicación en serie en ATmega32u4

4

Tengo un tablero teensy 2.0 y trato de usarlo para controlar este LCD a través de la serie TTL.

Conseguí que funcionara bien con mi Arduino uno y un código de Arduino de muestra, pero quiero hacerlo con el lenguaje teensy y C.

El teensy utiliza el ATmega32u4 y aquí está la hoja de datos para ese chip.

En la hoja de datos, a partir de la página 186, se encuentra la sección sobre USART. En la página 192 hay un código de ejemplo en lenguaje C sobre cómo inicializar el USART. Estoy confundido en un par de líneas y podría necesitar ayuda.

void USART_Init( unsigned int baud )
{
  /* Set baud rate */
  UBRRHn = (unsigned char)(baud>>8);
  UBRRLn = (unsigned char)baud;

  /*rest of code here*/
}

Primero, no tengo claro cuál debería ser el número de velocidad en baudios. Mi pantalla LCD requiere 9600 baudios con 1 bit de inicio, 1 bit de parada, sin bit de paridad y 8 bits de datos. En la página 189 de la hoja de datos del ATmega32u4 hice el cálculo de cuál debería ser la velocidad en baudios que, en el caso de la combinación teensy y LCD, debería ser 103 porque la frecuencia del chip es 16mhz y la velocidad en baudios es 9600. Esto también coincide con el número en la tabla en la página 213 de la hoja de datos del ATmega32u4. Entonces, ¿es este el número correcto que se pasaría a la función USART_Init para la variable en baudios?

También estoy confundido en las dos líneas que establecen la velocidad de transmisión. Entiendo que, según la página 209 de la hoja de datos de ATmega32u4, los registros de velocidad en baudios se dividen en un registro alto y bajo, pero solo se utilizan los bits 8:10 en el registro alto, lo que lo convierte en un registro combinado de 12 bits. Entonces, volviendo al código, no entiendo algunas cosas:

  1. ¿Por qué se está encasillando a un personaje sin firma porque supongo que UBRRHn debería estar en notación binaria?
  2. Tampoco entiendo la parte (baudios > > 8) porque si rellenas 103 para baudios obtienes (103 > > 8) y eso no está bien. ¿Alguien puede explicar esta línea para mí? Gracias.
UBRRHn = (unsigned char)(baud>>8);<br/>
UBRRLn = (unsigned char)baud;
  1. ¿Debe baud ser la versión binaria de 12 bits de 103 que es 00001100111? Si es así, ¿cómo se escribiría el código?

También, encontré algunos ejemplos de código (http://www.pjrc.com/teensy/uart.html) en el sitio web de teensy que configura el UART y configura la velocidad de transmisión de esta manera:

void uart_init(uint32_t baud)
{
    cli();
    UBRR1 = (F_CPU / 4 / baud - 1) / 2;

    /*rest of code here*/
}

Si conecto los números, se vería así:

UBRR1 = (16000000 / 4 / 9600 - 1) / 2; /* Which would equal 208 */
  1. El número 208 es diferente de 103, por lo que no entiendo de dónde sacan la ecuación para calcularlo.
  2. UBRRn solo se menciona en la hoja de datos de ATmega32u4 en las páginas 188 y 189. Parece que tiene el valor de UBRRHn y UBRRLn. El código anterior parece estar intentando configurar ambos al mismo tiempo pero como un int. Estoy tan confundido, ¿no es necesario que esté en notación binaria?

Bueno, estoy deseando superar esta joroba y seguir haciendo que mi LCD bailen. :)

    
pregunta rayjamesfun

2 respuestas

3

Para comprender todo esto, consulte la "Tabla 18-1. Ecuaciones para calcular la configuración del registro de velocidad en baudios" en la hoja de datos en la página 189. La ecuación que sugirió que encontró en algún código de ejemplo

UBRR1 = (F_CPU / 4 / baud - 1) / 2;

... es algo parecido a la ecuación para el modo de doble velocidad asíncrona (U2Xn = 1) ... pero no exactamente.

Si conoce la velocidad en baudios y la velocidad del cristal al que pretende operar, simplemente eliminaría los ajustes de registro de la "Tabla 18-9. Ejemplos de ajustes UBRRn para frecuencias de osciladores de uso común" en la hoja de datos página 210 y lo llamo un día. La única razón para usar cualquiera de esas ecuaciones es si desea poder cambiar las configuraciones dinámicamente en tiempo de ejecución por alguna razón (o si quiere hacer adelgazamiento "elegantemente" en el software, prefiero la certeza de tiempo de compilación para algo como esto para eliminar la duda).

Para la configuración que describiste en tu pregunta, eso sería:

UCSR1A = 0;                         // importantly U2X1 = 0
UCSR1B = 0;                         // interrupts enabled in here if you like
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); // no parity, 8 data bits, 1 stop bit
UCSR1D = 0;                         // no cts, no rts
UBRR1  = 103;                       // 9600 baud @ 16MHz XTAL with U2X1 = 0    

Como nota al margen, si bien el hardware almacena el registro de velocidad en baudios (UBBRn) como dos registros de 8 bits, en el software no es necesario tratarlo como tal. Usted puede acceder a los registros Alto y Bajo (por ejemplo, UBRR1H y UBRR1L respectivamente), pero también puede asigne (o lea) el registro "combinado" denominado como si fuera un registro de 16 bits.

UBRR1 = 0x0343; es funcionalmente equivalente a UBRR1H = 0x03; UBRR1L = 0x43;

    
respondido por el vicatcu
3

Un unsigned char siempre debe ser de 8 bits o un solo byte. Olvídese de que se trata de un "carácter", sino de un tipo de datos numérico del mismo tamaño que nuestros registros. Ya que estamos pasando un número que posiblemente podría tener 12 bits, nuestra función está aceptando un tipo de datos que es lo suficientemente grande para baud ( unsigned int ). Esto podría ser de 32 o 16 bits (no importa en este caso) dependiendo de nuestra arquitectura.

Para esta arquitectura, nuestros registros UBRRHn y UBRRLn tienen 1 byte cada uno. No tenemos un solo registro que sea lo suficientemente grande como para tomar ese valor de 12 bits, así que tenemos dos registros de 8 bits, y como mencionó, dividimos ese número de 12 bits en cada uno. UBRRHn toma los 4 bits superiores, mientras que UBRRLn toma los 8 inferiores.

Cambiamos las posiciones unsigned int 8 hacia abajo para obtener esos 4 bits superiores. Tomemos un ejemplo trivial con todos los bits '1':

baud = 4095;
UBRRHn = (unsigned char)(baud>>8);
// our shift: 0b0000111111111111 >> 8 == 0b0000000000001111
// after cast & assignment, UBRRHn == 0b00001111
UBRRLn = (unsigned char)baud;
// after cast & assignment, UBRRLn == 0b11111111

Nuestra conversión a unsigned char tomará los 8 bits más bajos ya que unsigned char es un tipo de datos de 8 bits.

No tengo tiempo para repasar el otro código de ejemplo, pero podría ser que esté usando alguna macro o algo en el momento de la compilación para dividirlo por él. Podría profundizar más y encontrar dónde se define UBBR1. Si no confías en él, no lo uses. Haga primero lo que sabe que es verdad para su configuración de hardware y pruébelo.

    
respondido por el Jon L

Lea otras preguntas en las etiquetas