Tengo una placa Teensy 2.0 y estoy tratando de usarla para controlar esta pantalla LCD a través de TTL en serie.
Conseguí que funcionara bien con mi Arduino uno y un código Arduino de muestra, pero quiero hacerlo con el lenguaje Teensy y C.
El adolescente usa el ATmega32u4 y aquí está la hoja de datos de ese chip.
En la hoja de datos, a partir de la página 186, está la sección sobre USART. En la página 192 hay un ejemplo de código de lenguaje C sobre cómo inicializar el USART. Estoy confundido en un par de líneas y me vendría bien un poco de 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 LCD pide 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 de diminuto y LCD debería ser 103 porque la frecuencia del chip es 16 MHz y la velocidad en baudios es 9600. Esto también coincide con el número en el gráfico 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 baudios?
También estoy confundido con las dos líneas que establecen la velocidad en baudios. Entiendo que, según la página 209 de la hoja de datos del ATmega32u4, los registros de velocidad en baudios se dividen en un registro bajo y alto, pero solo se usan 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:
UBRRHn = (unsigned char)(baud>>8);<br/>
UBRRLn = (unsigned char)baud;
Además, encontré un código de muestra (http://www.pjrc.com/teensy/uart.html) en el sitio web de Teensy que configura el UART y configura la velocidad en baudios 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 */
Bueno, tengo muchas ganas de superar este bache y pasar a hacer que mi LCD baile. :)
Para comprender todo esto, eche un vistazo a la "Tabla 18-1. Ecuaciones para calcular la configuración del registro de velocidad en baudios" de 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;
... está un poco cerca de la ecuación para el modo asíncrono de doble velocidad (U2Xn = 1)... pero no exactamente.
Si conoce la velocidad en baudios y la velocidad del cristal a la que pretende operar, simplemente sacaría la configuración del registro de la "Tabla 18-9. Ejemplos de configuración UBRRn para frecuencias de oscilador de uso común" en la página 210 de la hoja de datos y lo llamaría un día. La única razón para usar cualquiera de esas ecuaciones es si desea poder cambiar la configuración dinámicamente en tiempo de ejecución por algún motivo (o si desea hacer cosas "elegantes" en el software, prefiero compilar la certeza del tiempo para algo como esto para quitar dudas).
Para la configuración que describió en su 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, mientras que 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. Puede acceder a los registros Alto y Bajo (por ejemplo, UBRR1H y UBRR1L respectivamente), pero también puede asignar (o leer) el registro "combinado" nombrado como si fuera un registro de 16 bits .
UBRR1 = 0x0343;
es funcionalmente equivalente aUBRR1H = 0x03; UBRR1L = 0x43;
Un unsigned char
debe ser siempre de 8 bits o de un solo byte. Olvídese de que es un 'carácter' sino más bien un tipo de dato numérico que tiene el mismo tamaño que nuestros registros. Dado que estamos pasando un número que posiblemente podría tener un tamaño de 12 bits, nuestra función acepta 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
son de 1 byte cada uno. No tenemos un solo registro que sea lo suficientemente grande para tomar ese valor de 12 bits, por lo que tenemos dos registros de 8 bits y, como mencionaste, dividimos ese número de 12 bits en cada uno. UBRRHn
toma los 4 bits superiores, mientras que UBRRLn
toma los 8 inferiores.
Desplazamos las unsigned int
8 posiciones 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
Nuestro elenco unsigned char
tomará los 8 bits inferiores ya que unsigned char
es un tipo de datos de 8 bits.
No tengo tiempo para repasar el otro código de muestra, pero podría ser que esté usando alguna macro o algo así en tiempo de compilación para dividirlo por él. Puede profundizar más y encontrar dónde se define UBBR1. Si no confías en él, no lo uses. Primero haga lo que sabe que es cierto para su configuración de hardware y pruébelo.
dext0rb
rayjamesfun