Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Uart Es
Uart Es
UAR CAPÍTULO 11
opcionalmente transmitir un bit de paridad adicional como una simple medida de detección de
errores de transmisión. Por ejemplo, si la paridad es "par", el número de bits enviados que son
uno debe ser un número par; el bit de paridad se elige para cumplir con esta restricción. Si el
receptor ve un número impar de unos en la transmisión, entonces sabe que se ha producido un
error de transmisión. Finalmente, el UART del PIC32 puede ser ajustado a uno o dos bits de
parada, que son los que se envían al final de una transmisión.
La biblioteca NU32 usa un baudio de 230.400, ocho bits de datos, ningún bit de paridad
y un bit de parada. Escrito en taquigrafía, esto es 230.400/8N1. La paridad puede ser
impar, par o ninguna.
Por razones históricas, las opciones de baudios comunes incluyen 1200, 2400, 4800, 9600,
19.200, 38.400, 57.600, 115.200 y 230.400, pero cualquier opción es posible, siempre que
ambos dispositivos estén de acuerdo.
Según el Manual de Referencia, la UART del PIC32 es teóricamente capaz de baudios de
hasta 20 M; sin embargo, en la práctica, el máximo baudios alcanzable es mucho menor.
La comunicación UART es asincrónica, lo que significa que no hay una línea de reloj para
mantener los dos dispositivos sincronizados. Debido a las diferencias en las frecuencias de reloj
de los dos dispositivos, los baudios de cada uno de ellos pueden ser ligeramente diferentes, y los
dispositivos UART pueden manejar pequeñas diferencias resincronizando sus relojes de baudios
en cada transmisión.
La figura 11.1 muestra una transmisión UART típica. Cuando no se transmite, la línea TX
es alta. Para iniciar una transmisión, la UART baja la TX por un período de un baudio. Este
bit de inicio le dice al receptor que una transmisión ha comenzado para que el receptor pueda
iniciar su reloj de baudios y comenzar a recibir bits. A continuación, se envían los bits de
datos. Cada bit se mantiene en la línea durante un período de baudios. Los bits se envían
primero el bit menos significativo (por ejemplo, el primer bit enviado para 0b11001000
será un cero). Después de los bits de datos, se puede enviar opcionalmente un bit de paridad.
Finalmente, el transmisor mantiene la línea en alto, transmitiendo uno o dos bits de parada.
Después de que se hayan transmitido los bits de parada, puede iniciarse otra transmisión; de
este modo, el uso de dos bits de parada proporciona a los dispositivos un tiempo de
procesamiento adicional entre las transmisiones. El bit de inicio, el bit de paridad y los bits
de parada son bits de control: no contienen datos. Por lo tanto, el baudio no corresponde
directamente a la velocidad de los datos.
A medida que la UART recibe datos, el hardware cambia cada bit en un registro. Cuando se ha
recibido un byte completo, ese byte se transfiere a la cola de primeras entradas y primeras
salidas (FIFO) de la UART. Al transmitir los datos, el software carga los bytes en el TX FIFO.
El hardware entonces carga los bytes del FIFO en un registro de desplazamiento, que los envía
por el cable. Si cualquiera de los FIFO está lleno y
Id Co Bi Bi Bi Bi Bi Bi Bi Bi D
le mi t t t t3 t4 t5 t6 t7 et
en 0 1 2 én
za ga
se
Figura 11.1
Transmisión UART de 0b10110010 con 8 bits de datos, sin paridad, y un bit de parada.
UART 161
es necesario añadir otro byte, se produce una condición de desbordamiento y se pierden los
datos. Para evitar una sobrecarga de TX FIFO, el software no debería intentar escribir en la
UART a menos que el TX FIFO tenga espacio. Para evitar un desbordamiento de RX FIFO, el
software debe leer el RX FIFO lo suficientemente rápido para que siempre tenga espacio
cuando lleguen los datos. El hardware mantiene banderas que indican el estado de los FIFO y
también puede interrumpir en función del número de elementos en los FIFO.
Una característica opcional llamada control de flujo de hardware puede ayudar al software a
prevenir los excesos. El control de flujo por hardware requiere dos cables adicionales:
solicitud de envío (RTS) y autorización de envío (CTS). 1 Cuando el RX FIFO está lleno, el
hardware de UART desactiva (impulsa en alto) el RTS, que le dice al DTE que no envíe
datos. Cuando el RX FIFO tiene espacio disponible, el hardware afirma (unidades bajas)
RTS, lo que permite al DTE enviar datos. El DTE controla el CTS. Cuando el DTE
des-asegura (conduce alto) CTS, el PIC32 no transmitirá datos. Para que el control de flujo
por hardware funcione, tanto el DTE como el PIC32 deben respetar las señales de control de
flujo. Por defecto, cuando usas make screen o make putty, esos emuladores de terminal
configuran tu DTE para usar el control de flujo por hardware.
Estos son los fundamentos de la operación de la UART. Existen muchas otras opciones,
demasiadas para cubrir aquí. El principio rector de toda operación UART, sin embargo, sigue
siendo el mismo: ambos extremos de la comunicación deben estar de acuerdo en todas las
opciones. Al interactuar con un dispositivo específico, lea su hoja de datos y seleccione las
opciones apropiadas.
11.2 Detalles
A continuación se describe el registro de la UART. La "x" en los nombres SFR significa
UART número 1 a 6. Todos los bits están por defecto a cero excepto dos bits de sólo
lectura en UxSTA.
UxMODE Activa o desactiva la UART. Determina la paridad, el número de bits de datos, el
número de bits de parada y el método de control de flujo.
UxMODE×15 )o UxMODEbits.ON: cuando se ajusta a uno, activa la UART.
UxMODE×9:8 )o UxMODEbits.UEN: Determina qué pines usa la UART.
Las opciones más comunes son
0b00Sólo se utilizan el UxTX y el UxRX (el mínimo requerido para
la comunicación UART).
0b10UxTX , UxRX, UxCTS, y UxRTS se utilizan. Esto permite el control
de flujo por hardware.
UxMODE×3 )o UxMODEbits.BRGH: Se llama "bit generador de alta tasa de baudios" y
controla el valor de un divisor M usado en el cálculo de la tasa de baudios (ver el
SFR UxBRG). Si este bit es 1, M = 4, y si es 0, M = 16.
1
Algunas UART del PIC32 no tienen líneas de control de flujo por hardware, y los pines de control de flujo de una
UART pueden coincidir con las líneas RX y TX de otra UART. Por ejemplo, el uso de UART3 con control de
flujo impide el uso de UART6.
162Capítulo 11
este bit elimina los datos en el buffer de recepción, por lo que es posible que desee
leer los bytes en el buffer de recepción antes de limpiarlo.
UxSTA×0)o UxSTAbits.URXDA: Cuando está configurado, indica que la memoria
intermedia de recepción contiene datos.
UxTXREG Usar este SFR para transmitir datos. Escribir en UxTXREG coloca los
datos en un FIFO de hardware de ocho bytes de largo. El transmisor elimina los
datos del FIFO y los carga en un registro de desplazamiento interno, UxTSR, donde
los datos se desplazan hacia la línea de TX, bit a bit. Una vez terminado el
desplazamiento, el hardware elimina el siguiente byte y comienza a transmitirlo.
UxRXREG Usar este SFR para recibir datos. El hardware cambia los datos recibidos bit a
bit en un registro de cambio de RX interno. Después de recibir un byte completo, el
hardware lo transfiere del registro de desplazamiento al RX FIFO. La lectura de
UxRXREG elimina un byte del RX FIFO. Si no lee de UxRXREG con suficiente
frecuencia, el FIFO de RX puede sobrecargarse. Si el FIFO está lleno, los bytes recibidos
posteriormente se descartan y se fija un indicador de estado de error de sobrecarga.
UxBRG controla el baudio. El valor de este registro debe ser fijado para lograr el baudio B
deseado de acuerdo con la siguiente ecuación:
FPB
UxBRG 1 (11.1)
=
M×B
En nuestro primer ejemplo, el PIC32 usa la UART1 para hablar consigo mismo. Conecta
U1RX (RD2) a U1TX (RD3). El programa usa la biblioteca NU32 y UART3 para pedir al
usuario un solo byte,
164Capítulo 11
lo envía dos veces de U1TX a U1RX, y reporta el byte que fue leído en U1RX. Configuramos
el baudio a una tasa extremadamente baja (100) para que pueda ver fácilmente la transmisión
en un osciloscopio. Si se pone el osciloscopio en modo de captura única y se dispara en el
flanco descendente, el osciloscopio capturará la señal desde el principio de la transmisión,
cuando se envíe el primer bit de inicio. El envío del byte dos veces permite verificar los bits
de parada.
Muestra de código 11.1 uart_loop.c. Código de UART que habla por sí mismo.
#incluyen constantes "NU32.h" //, funciones para el arranque y UART
// Configuraremos UART1 a una velocidad de baudios lenta para que puedas examinar la señal en un
telescopio.
// Conecta los pines de RX y TX de la UART1 para que la UART pueda comunicarse consigo misma.
int main(void) {
char msg[100] = {};
NU32_Startup(); // caché encendido, interrupciones encendidas, LED/botón encendido, UART encendido
// U1BRG = Fpb/(M * baud) - 1 (nota U1MODEbits.BRGH = 0 por defecto, por lo que M = 16)
// Preparado para 100 baudios. Esto significa 100 bits /seg o 1
bit/ 1/10ms U1BRG = 49999;// 80 M/(16*100) - 1 = 49,999
U1MODEbits.ON = 1; // enciende el uart
mientras que (U1STAbits.UTXBF) { // espera a que UART esté listo para transmitir
;
}
U1TXREG = datos; // escribir dos veces para poder ver el
bit de parada U1TXREG = datos;
while(!U1STAbits.URXDA) { // encuesta para ver si hay datos para leer en RX FIFO
;
}
datos = U1RXREG; // los datos han llegado; lee el byte while(!
U1STAbits.URXDA) { // espera hasta que haya más datos para leer en RX FIFO
;
}
Datos = U1RXREG; // sobrescribiendo los datos de la lectura anterior!
podría comprobar si el mismo sprintf(msg,"Read 0x%x from UART1\r\n",data);
NU32_WriteUART3(msg);
}
...devuelve 0;
}
UART 165
Muestra de código 11.2 uart_int.c. Código UART que utiliza interrupciones para recibir
datos.
#incluyen constantes "NU32.h" //, funciones para el arranque y UART
int main(void) {
NU32_Startup(); // caché encendida, interrupciones encendidas,
LED/botón encendido, UART encendido NU32_LED1 = 1;
NU32_LED2 = 1;
builtin_disable_interrupts();
// Ponga el baudio a 230400, para que coincida con el emulador de terminal; use el
valor por defecto 8N1 de UART U3MODEbits.BRGH = 0;
U3BRG = ((NU32_SYS_FREQ / 230400) / 16) - 1;
IPC7bits.U3IP = 1; // prioridad de
interrupción IEC1bits.U3RXIE = 1; // habilitar la
interrupción de RX
// enciende UART1
U3MODEbits.ON = 1;
builtin_enable_interrupts();
while(1) {
;
}
...devuelve 0;
}
// habilitar la caché
// Este comando establece el registro CP0 CONFIG
// los 4 bits inferiores pueden ser 0b0011 (0x3) o 0b0010 (0x2)
// para indicar que kseg0 es cacheable (0x3) o no cacheable (0x2)
// ver Capítulo 2 "CPU para dispositivos con núcleo M4K" del manual de referencia del PIC32
// la mayoría de los otros bits tienen valores prescritos
// el microchip no proporciona una macro _CP0_SET_CONFIG, así que usamos directamente
// el comando incorporado del compilador _mtc0
// para desactivar la caché, use 0xa4210582
builtin_mtc0(_CP0_CONFIG, _CP0_CONFIG_SELECT, 0xa4210583);
// Habilitar interrupciones
multivectoriales INTCONbits.MVEC
= 0x1;
// Activar el Uart
U3MODEbits.ON = 1;
builtin_enable_interrupts();
168Capítulo 11
// Leído de UART3
// Bloquear otras funciones hasta que se obtenga un '\r' o '\N'.
// envía el puntero a tu matriz de caracteres y el número de elementos en la
matriz vacía NU32_ReadUART3(char * mensaje, int maxLength) {
Datos de caracteres = 0;
int complete = 0, num_bytes = 0;
// ...hasta que consigas un "r" o
"n" mientras que...
si (U3STAbits.URXDA) { // si hay datos
disponibles datos = U3RXREG; // leer los
datos
si ((data == '\n') || (data == '\r'))
{ complete = 1;
} más {
message[num_bytes] = data;
++número_de_bites;
// pasar el ratón por encima si la
matriz es demasiado pequeña si
(num_bytes >= maxLength) {
num_bytes = 0;
}
}
}
}
// termina la cadena de
mensajes[num_bytes] =
'\0';
}
A menudo es deseable transmitir a la computadora los datos recogidos por el PIC32. Por
ejemplo, un ISR de frecuencia fija podría tomar muestras de datos de un sensor y luego
enviarlas a su computadora para que las grafique. Sin embargo, el ISR puede recoger
muestras a una velocidad mucho más alta de la que pueden enviarse a través de la UART. En
este caso, algunos de los datos tienen que ser descartados. El
− proceso de mantener sólo un
dato por cada N recolectado (desechando N 1) se llama diezmo. 2 El diezmo es
común en el procesamiento de señales.
Además del diezmo, otro concepto que permite la transmisión de datos de un ISR es el de un
un búfer circular. Un buffer circular (o de anillo) es una implementación de un FIFO, como el de la
UART
2
El origen de este término es una práctica disciplinaria del ejército romano, por la cual uno de cada diez soldados
que se había desempeñado de manera vergonzosa fue asesinado.
UART 169
70
6 1 Lea
Escriba 5 2
43
Figura 11.2
Un búfer circular de ocho elementos (FIFO), donde el índice de escritura apunta actualmente al elemento 5 y
al
El índice de lectura apunta actualmente al elemento 1.
TX y RX FIFO. Se implementa un búfer circular como una matriz y dos variables de índice:
escritura y lectura (véase la figura 11.2). Los datos se añaden a la matriz en el lugar de
escritura y se leen desde el lugar de lectura, tras lo cual se incrementan los índices. Cuando
los índices llegan al final de la matriz, se envuelven hasta el principio. Si los índices de
lectura y escritura son iguales, el búfer está vacío. Si el índice de escritura está una
ranura detrás del índice de lectura, el búfer está lleno.
Los buffers circulares son útiles para compartir datos entre las interrupciones y el código de la
línea principal. La ISR puede escribir datos en el buffer mientras que el código de línea
principal lee del buffer y envía los datos a través de la UART.
La Muestra de Código 11.4 demuestra el concepto de diezmar y la Muestra de Código 11.5
demuestra el concepto de un buffer circular. Ambos programas envían 5000 muestras de datos
del PIC32 al ordenador central. La Muestra de Código 11.4 se titula batch.c porque todos los
datos diezmados se almacenan primero en una matriz en la RAM, y luego se envían a través
de la UART en un lote. La Muestra de Código 11.5 se llama circ_buf.c porque los datos son
enviados usando un buffer circular. El uso de un búfer circular
(a) permite que la memoria intermedia utilice menos RAM que la matriz en batch.c y b)
permite que los datos se envíen inmediatamente, no sólo en un lote después de que se hayan
recogido todos.
#define DECIMATE 3// sólo envía cada 4 muestras (el conteo comienza en
cero) #define NSAMPLES 5000// almacena 5000 muestras
++curr;
}
}
++cuenta;
IFS0bits.T1IF = 0; // borrar la bandera de interrupción
}
int main(void) {
int i = 0;
Char Buffer[100] = {};
NU32_Startup(); // caché encendido, interrupciones encendidas, LED/botón encendido,
UART encendido
int buffer_empty() {// return true if the buffer is empty (read = write)
return read == write;
}
int buffer_read() {// lee de la ubicación actual del buffer; asume que el buffer no
está vacío int val = data_buf[read];
++lectura; // incrementos índice de lectura
if(read >= BUFLEN) { // envuelve el índice de lectura si es
necesario leer = 0;
}
Devuélvelo a Val;
}
int main(void) {
int sent = 0;
char msg[100] = {};
NU32_Startup(); // caché encendido, interrupciones encendidas, LED/botón
encendido, UART encendido
mientras que(1) {
;
}
...devuelve 0;
}
172Capítulo 11
En circ_buf.c, si el búfer circular está lleno, se pierden datos. Mientras que circ_buf .c está
escrito para enviar un número fijo de muestras, puede ser fácilmente modificado para
transmitir muestras indefinidamente. Si el baudio de la UART es suficientemente superior a la
velocidad a la que se generan los bits de datos en la ISR, la transmisión de datos sin pérdidas
puede realizarse indefinidamente. El búfer circular simplemente proporciona cierto
amortiguamiento en los casos en que la comunicación se retrasa o se interrumpe
temporalmente.
Hasta ahora, cuando hemos usado la UART para comunicarnos con un ordenador, hemos
abierto el puerto serie en un emulador de terminal. MATLAB también puede abrir puertos
serie, permitiendo la comunicación y el trazado de datos desde el PIC32. Como primer
ejemplo, nos comunicaremos con talkingPIC.c de MATLAB.
Primero, carga talkingPIC.c en el PIC32 (ver capítulo 1 para el código). Luego, abre
MATLAB y edita el talkingPIC.m. Necesitarás editar la primera línea y establecer el puerto
como el valor PORT de tu Makefile.
Muestra de código 11.6 talkingPIC.m. Código MATLAB simple para hablar con
talkingPIC en el PIC32.
port='COM3'; % Edita esto con el nombre correcto de tu PUERTO.
Abriendo la conexión en
serie abierta;
Cerrando la conexión en
serie fclose(mySerial)
El código talkingPIC.m abre un puerto serial, envía tres valores numéricos al PIC32,
recibe los valores y cierra el puerto. Ejecuta talkingPIC .c en tu PIC32, y luego ejecuta
talkingPIC.m en MATLAB.
UART 173
También podemos combinar MATLAB con batch.c o circ_buf.c, permitiéndonos trazar los
datos recibidos de un ISR. El siguiente ejemplo lee los datos producidos por batch. c o
circ_buf.c y los traza en MATLAB. Una vez más, cambia la variable del puerto para que
coincida con el puerto serie que utiliza tu PIC32.
Muestra de código 11.7 uart_plot.m. Código MATLAB para trazar los datos
recibidos de la UART.
% de datos de streaming en el
puerto del laboratorio
='/dev/ttyUSB0'.
datos = ceros(len,1);
para i = 1:len
datos(i) = fscanf(miSerie,'%d'); % leer cada
elemento final
También puedes comunicarte con el PIC32 desde el lenguaje de programación Python. Este
lenguaje de programación de libre acceso tiene muchas librerías disponibles que ayudan a
que sea usado como una alternativa a MATLAB. Para comunicarse a través del puerto serie
se necesita la biblioteca pyserial. Para el trazado, usamos las bibliotecas matplotlib y numpy.
El siguiente código lee los datos del PIC32 y los traza. Al igual que con el código MATLAB,
necesitas especificar tu propio puerto donde se define la variable del puerto. Este código
trazará los datos generados por batch.c o
circ_buf.c.
Muestra de código 11.8 uart_plot.py. Código Python para graficar los datos
recibidos de la UART.
#!/usr/bin/python
# Datos de la gráfica del PIC32 en la pitón
# requiere la importación de series de
pyseries, matplotlib y numpy
importar matplotlib.pyplot como plt
174Capítulo 11
plt.plot(x,y)
plt.show()
3
Una advertencia se produce a tasas de baudios más altas. El XBee genera su baudio dividiendo una señal de reloj
interno. Este reloj no alcanza realmente un baudio de 115.200, sin embargo, cuando se ajusta a 115.200 el
baudio es en realidad de 111.000. Tales desajustes en la tasa de baudios son un problema común cuando se usan
UARTs. Debido a las tolerancias de la sincronización de la UART, el XBee puede funcionar durante un tiempo
pero ocasionalmente experimenta fallos. La solución es ajustar su baudio a 111.000 para que coincida con el
baudio real del XBee.
UART 175
Figura 11.3
Una radio XBee 802.15.4. (Imagen cortesía de Digi International, digi.com.)
11.6 Ejercicios
1. Trace la forma de onda para una UART enviando el byte 0b11011001, asumiendo
9600 baudios, sin paridad, 8 bits de datos, y un bit de parada.
176Capítulo 11
Más lecturas
Manual de referencia de la familia PIC32. Sección 21: UART. (2012). Microchip Technology Inc.
Módulos de RF XBee/XBee-PRO (v1.xEx). (2009). Digi International