Control de periféricos y comunicación
El programa deja de ser un ejercicio cuando enciende un LED real. Del otro lado del cable hay un microcontrolador esperando bytes, y hay que ponerse de acuerdo en qué significa cada uno.
01Del programa al mundo físico
Un programa que sólo imprime en pantalla no necesita saber nada del hardware. Apenas hay que encender un LED o leer un sensor, aparecen tres preguntas: por dónde salen los datos, con qué velocidad y qué significa cada byte.
| Interfaz | Velocidad típica | Dónde se usa |
|---|---|---|
| Serie asincrónica (UART/USB-serie) | 9600 a 921 600 baudios | Lo más común entre PC y microcontrolador |
| I²C | 100 kHz a 1 MHz | Sensores y periféricos dentro de una placa |
| SPI | 1 a 50 MHz | Memorias, pantallas, conversores rápidos |
| USB nativo | 12 a 480 Mbit/s | Instrumentos y adquisición de datos |
| Ethernet / TCP-IP | 10 a 1000 Mbit/s | Equipos en red, industria |
En la computadora, el puerto serie se abre como si fuera un archivo: se configura, se escribe y se lee.
En Python con pyserial son tres líneas; en C, con termios en Linux o
CreateFile en Windows, unas cuantas más, pero la idea es la misma.
import serial
p = serial.Serial("COM3", 115200, timeout=0.2)
p.write(b"\xAA\x02\x01\x64\x67")
respuesta = p.read(5)
02Los parámetros que hay que acordar
Las dos puntas tienen que estar configuradas igual o no se entienden. Con 8N1 —ocho bits de datos, sin paridad, un bit de parada— cada byte viaja en diez bits:
- Velocidad en baudios: 9600, 19 200, 38 400, 57 600, 115 200…
- Bits de datos, casi siempre 8.
- Paridad: ninguna, par o impar. Detecta un bit cambiado, no dos.
- Bits de parada: 1 o 2.
- Control de flujo: por hardware (RTS/CTS) o ninguno.
El UART de un microcontrolador trabaja a 3,3 o 5 V; un puerto RS-232 de verdad usa ±12 V con la lógica invertida. Conectarlos directamente quema el microcontrolador. Entre medio va un adaptador —un MAX232 o un conversor USB-serie— y, si las tensiones difieren, un adaptador de nivel.
03Inventar un protocolo
El puerto transporta bytes sueltos; el significado lo pone el protocolo. Un esquema mínimo que funciona en la práctica tiene cuatro partes:
| Campo | Para qué |
|---|---|
| Byte de arranque | Marca dónde empieza la trama, para poder resincronizar |
| Comando y longitud | Qué se pide y cuántos bytes de datos vienen |
| Datos | El contenido |
| Verificación | Detecta si algo llegó mal: suma, XOR o CRC |
Cambiá el comando y el dato, elegí el método de verificación y probá corromper un byte para ver si el receptor se da cuenta.
04Suma, XOR y CRC
| Método | Cómo se calcula | Qué detecta |
|---|---|---|
| Suma de verificación | \( \sum b_i \bmod 256 \) | Un byte cambiado; no el orden |
| XOR | \( b_1 \oplus b_2 \oplus \cdots \oplus b_n \) | Un bit cambiado por columna; falla con dos |
| CRC-8 | División binaria por un polinomio | Todas las ráfagas de hasta 8 bits |
| CRC-16 / CRC-32 | Igual, con polinomio más largo | Lo que se usa en Modbus, USB y Ethernet |
La suma es la más fácil de escribir y la más débil: si dos bytes cambian de forma compensada, no se entera. El CRC es una división de polinomios en aritmética binaria y detecta prácticamente cualquier error de transmisión real; por eso lo usan todos los protocolos serios. Se implementa con una tabla de 256 entradas y es rapidísimo, incluso en un microcontrolador chico.
05Esperar sin trabarse
El error más común al comunicarse con un equipo es quedarse esperando para siempre. Hay tres estrategias, y conviene conocer las tres:
- Lectura con tiempo de espera.
timeouten el puerto: si el equipo no contesta en 200 ms, la lectura vuelve vacía y el programa decide qué hacer. Es lo mínimo indispensable. - Hilo dedicado. Un hilo lee el puerto y deposita las tramas en una cola; el programa principal la consume cuando puede. Es el esquema productor-consumidor.
- Entrada-salida asincrónica. El sistema avisa cuando hay datos, sin que nadie espere.
El microcontrolador tiene el mismo problema al revés: si atiende el puerto dentro del bucle principal, pierde bytes mientras hace otra cosa. Por eso la recepción se hace en la interrupción del UART, que guarda cada byte en un buffer circular, y el programa principal procesa la trama cuando está completa.
06En el laboratorio
Programar el microcontrolador para que devuelva cada byte que recibe. Desde la computadora, medir el tiempo de ida y vuelta a 9600 y a 115 200 baudios, y comparar con 10 bits por byte.
Definir e implementar el protocolo de esta página en las dos puntas: encender y apagar una salida, fijar un PWM y leer un canal analógico. Documentar la trama en una tabla.
Desconectar el cable a mitad de una transmisión, o bajar la velocidad de un lado. Verificar que el receptor descarta las tramas mal formadas y vuelve a sincronizar con el byte de arranque, en lugar de colgarse.
07Errores frecuentes
- Velocidades distintas en cada punta. Llegan bytes, pero con basura.
- Leer sin tiempo de espera y dejar el programa colgado para siempre.
- Suponer que una lectura devuelve la trama entera. Puede volver partida: hay que acumular hasta tener la longitud declarada.
- Conectar 5 V a una entrada de 3,3 V.
- Olvidar la masa común entre los dos equipos.
- Confiar en que el canal es perfecto y no verificar nada.
08Autoevaluación
¿Cuántos bytes por segundo entran a 115 200 baudios en 8N1?
Cada byte ocupa 10 bits, así que 11 520 bytes/s, unos 87 µs por byte.
¿Para qué sirve el byte de arranque de una trama?
Para poder resincronizar: si se perdió un byte, el receptor descarta hasta encontrar el siguiente arranque en lugar de interpretar basura.
¿Por qué el CRC es mejor que la suma?
Porque detecta ráfagas de errores y combinaciones que la suma no ve, como dos bytes que cambian de forma compensada.
¿Dónde conviene recibir los bytes en el microcontrolador?
En la interrupción del UART, guardándolos en un buffer circular. En el bucle principal se perderían mientras el programa hace otra cosa.
¿Qué pasa si se conectan un UART de 3,3 V y un puerto RS-232?
El RS-232 usa ±12 V con lógica invertida: quema la entrada. Hace falta un adaptador como el MAX232.
Una lectura devolvió 3 bytes de una trama de 6. ¿Qué hay que hacer?
Acumularlos y seguir leyendo hasta completar la longitud declarada, o descartar por tiempo de espera. La lectura serie no garantiza entregar la trama entera de una vez.
09Para ampliar
- Jan Axelson. Serial Port Complete. 2.ª ed., Lakeview Research, 2007. Todo sobre puertos serie, USB-serie y su programación en la PC.
- Michael Barr y Anthony Massa. Programming Embedded Systems in C and C++. 2.ª ed., O'Reilly, 2006. El lado del microcontrolador: interrupciones, buffers y controladores de periféricos.
- Documentación de pyserial. pySerial Documentation. Versión actual. La biblioteca estándar para hablar con un puerto serie desde Python.