En la comunicación serial asíncrona unidireccional, ¿cómo sincroniza el receptor sus bytes?

Quiero hacer un sistema en serie sobre RF para recibir mensajes enviados desde una computadora, para poder entender cómo funciona la radio digital en el metal desnudo. La única parte que no entiendo es cómo un remitente y un receptor sincronizan el inicio y el final de sus bytes. Parece que sería muy fácil perder la sincronización y terminar con todo desplazado unos pocos bits. ¿Cómo sincronizan dos nodos seriales el inicio y el final de sus bytes?

Podría ser educativo mirar la recuperación del reloj. Enlace: en.m.wikipedia.org/wiki/Clock_recovery
Lo hacen con bits de sincronización.

Respuestas (4)

La temporización de UART para datos asincrónicos se basa en el conocimiento de la tasa de datos y en tener un reloj que suele ser 16 veces más rápido. La mitad superior de la imagen muestra cómo se vuelven a sincronizar los datos y la mitad inferior muestra un sistema mal sincronizado (velocidad de reloj de 13x) solo como ejemplo: -

ingrese la descripción de la imagen aquí

En ausencia de bordes de datos, el reloj cronometrado correctamente puede muestrear los datos prácticamente en el medio del símbolo. En la imagen inferior, y sin bordes de datos para volver a programar las cosas, el reloj 13x eventualmente cometerá un error.

Para la "imagen de radio" más grande, debe enviar un preámbulo para que las cosas comiencen, es decir, no puede esperar que se bloquee de inmediato porque hay muchos factores involucrados. Aquí hay una imagen que dibujé hace algún tiempo que explica cómo funcionaría un preámbulo en un transmisor y receptor de radio FM simple: -

ingrese la descripción de la imagen aquí

Y aquí está la respuesta anterior que incluía ese diagrama. Más información útil contenida.

Los UART (rs232) tienen un bit de inicio (0) y un bit de parada (1). ver el diagrama de Andy. Pero usan cable y el ruido es muy bajo, básicamente ninguno.

En un enlace ruidoso, esto funciona muy mal. Si el bit de inicio es incorrecto, todo lo que sigue es incorrecto y permanece así.

Las radios generalmente no hacen esto, es más probable que tengan un preámbulo que tenga una ráfaga de calentamiento de 1/0 para que el tx y rx se estabilicen, y obtengan sincronización de bits, luego un bloque de sincronización mágico, por ejemplo, un patrón único de 32 bits para inicialmente sincronizar bloques, luego bloques de datos con corrección de errores. Tenga en cuenta que los bloques de datos con errores corregidos pueden sincronizarse automáticamente; solo son válidos cuando la sincronización es correcta.

Los códigos se eligen para tener siempre suficientes transiciones 1/0 para mantener la sincronización de bits. es decir. no puede obtener una ejecución de 32 1, siempre habrá una transición cada N bits, en el peor de los casos.


Si usa un UART por radio, el preámbulo debe ser caracteres que tengan una sola transición 0/1, para que el UART pueda volver a sincronizarse. Como debería ser obvio, si sus datos fueran 1/0/1/0, el uart nunca sabría qué borde era el bit de inicio. Como puede ver en el diagrama de Andy, quiere tener un saldo aproximadamente igual a 1/0. Entonces 0xF0 es ideal, la secuencia será start=0 0000 1111 stop=1

En la comunicación asíncrona tienes una velocidad definida, la tasa de baudios.

El receptor sabe cuánto tiempo es un bit. Espera un borde y luego comienza a contar hasta que está en la mitad del tiempo de bits. Luego muestrea la entrada.

La espera de un borde se realiza mediante 'sobremuestreo'. Lees el estado de entrada mucho más rápido que la tasa de bits. Lo común es usar un sobremuestreo de 16x, pero 8x también funciona.

Existe un software gratuito que implementa un UART.
Si desea ver cómo se hace en hardware, busque el código fuente de Verilog. Si sabe C, casi puede * leer el código Verilog.

* Aparte de algunos detalles muy importantes :-)!

Lo siento, me perdí la parte de 'inicio y final de sus bytes'.

Un UART comienza con un bit de inicio que siempre es bajo. Termina con un bit de parada que siempre es alto. Por lo tanto, espera un 0 en la línea y sabe que ese es el bit de inicio. Luego cuenta, por ejemplo, 10 bits (inicio, 8 datos, parada) y el décimo bit debe ser alto. Es muy posible que un flujo de bits continuo se muestree en el punto equivocado y aún respete el protocolo 'start is low stop is high'. Por lo tanto, trato de jadear entre bytes para evitar esto.

Podría ser instructivo observar un algoritmo más simple para encontrar los bits de inicio y fin. Primero, muestree la entrada a 4 veces la tasa de bits.

Si su velocidad de datos es de 9.600 bits por segundo, querrá muestrearlo a 38.400 Hz.

Cuando no hay transmisión, obtendrá una gran cantidad de ruido y la entrada de muestra puede tener altos y bajos aleatorios.

Cuando se envía un bit de inicio, lo detectará en al menos 3 muestras consecutivas. A partir de entonces, muestreará cada 4 muestras como el bit real recibido, compensado por una muestra para que esté cerca de la mitad de cada bit.

Eventualmente recibirá el bit de parada; si no es correcto, puede descartar todos los datos e intentarlo de nuevo, esperando un bit de inicio.

Ese es el caso sencillo. Una vez que tenga eso funcionando, encontrará que todavía está obteniendo datos incorrectos, y ahí es donde emplea más técnicas para recuperar los datos:

  • En lugar de usar solo una muestra cerca de la mitad de cada bit, mire las tres muestras que deberían ocurrir dentro del tiempo del bit y use el voto de la mayoría para determinar el valor real del bit.
  • Aumente la frecuencia de muestreo a 8x o 16x, lo que le dará una cantidad mucho mayor de muestras por bit para usar y lo acercará a recopilar información en todo el bit en lugar de solo 3/4 en el medio.
  • Almacene el flujo de datos mientras lo recibe y use un correlador que se mueva a lo largo del flujo para encontrar los bits de inicio y parada. De esta manera, no descartará un posible byte porque obtuvo un bit de inicio incorrecto justo antes de los datos reales.
  • En lugar de muestrear en medio de los bytes, busque las transiciones: RF envía transiciones mejor que los niveles estáticos. Encuentre el comienzo del bit de inicio, luego use una pequeña ventana alrededor de cada transición de bit, observe si hay una transición y luego tendrá información sobre el bit anterior y el bit siguiente.

Sin embargo, las señales directas de USART no son apropiadas para RF. Considere buscar en la codificación de Manchester. En lugar de enviar datos como máximos/mínimos, los envía como transiciones de mayor a menor o de menor a mayor. Hace que la recuperación del reloj sea mucho más fácil, ya que codifica el reloj en cada bit y opera en las transiciones, que es el amigo natural de RF. No puedes enviarlo tan rápido, pero será mucho más confiable.

Considere también la detección de errores y, si es posible, la corrección de errores. Con una simple detección de errores, podrá verificar si los ajustes a su algoritmo están mejorando la señal o no de manera objetiva.

Usar un múltiplo de sobremuestreo impar funciona un poco mejor que uno par. El uso de un sobremuestreo de 3x, por ejemplo, permite una pendiente completa de +/- 1/3 de un bit de tiempo, mientras que el uso de 4x solo permite uno para -1/2 +1/4 o -1/4 +1 /2.
@supercat Probablemente sea una buena discusión para una pregunta de seguimiento. Ambos tienen méritos, sin embargo, con 3 realmente solo puedes confiar en una muestra, los otros dos podrían estar muy cerca de la transición y sin un esfuerzo adicional no sabes en cuál de los otros dos puedes confiar. Con 4 obtienes dos muestras que se sabe que están al menos a 1/4 de bit de distancia de la transición. Siendo este un ejemplo simple, no fui más allá, pero ciertamente, dependiendo del ruido real experimentado, uno u otro podría funcionar mejor.
Con 3x, obtienes una muestra que está al menos a 1/3 de un bit de tiempo del borde. Con 4x, obtienes dos que están a 1/4 de distancia. Si ambas muestras coinciden en todos los bits, eso sugeriría que probablemente sean buenas, pero si no coinciden, es posible que no sepa cuál es la "correcta". Por cierto, otro enfoque que me sorprende que no veo implementado con más frecuencia es usar un sobremuestreo 2x pero restablecer el temporizador cuando se recibe el bit de inicio.
@supercat Sí, y podríamos seguir. Es una discusión interesante porque estoy seguro de que hay casos en los que uno tendría más sentido que el otro y viceversa, según los requisitos y el entorno específico. Personalmente, no usaría ninguno de los dos a menos que sea necesario; ambos realmente están raspando el fondo del barril. Usé una frecuencia de muestreo baja para ilustrar la respuesta y simplificarla, pero sugiero una frecuencia de muestreo más alta en general.