¿Qué causa los errores UART?

8

Me gustaría saber para saber por qué ocurren los errores de UART y cuándo se deben verificar dichos errores. Aquí hay una publicación que pregunta sobre el manejo de errores individuales, como desbordamiento, paridad, etc. Tengo claro por qué ocurre el desbordamiento de datos, por qué ocurre el error de paridad, pero me gustaría saber cuál es la causa raíz. Mi pregunta se centra más en por qué podrían ocurrir estos errores (razones físicas) y cuándo se debe hacer que la verificación de errores sea un factor para su aplicación.

Hasta ahora, mi programa parece funcionar muy bien (sin verificación de errores), pero sé que el ruido puede estropear las cosas. ¿Cómo podría simular condiciones que podrían hacer que los puertos UART Rx / Tx fallen?

usuario791953
fuente

Respuestas:

8

Hay varias fuentes potenciales de ruido en cualquier circuito. Algunos de los más comunes incluyen:

  • Fuentes de alimentación mal reguladas;
  • Fuentes de alimentación conmutadas;
  • Desacoplamiento capacitivo insuficiente de los rieles de alimentación cerca de la MCU;
  • Acoplamiento inductivo de fuentes electromagnéticas cercanas (incluyendo 50 o 60Hz de la red eléctrica; incluso si el circuito funciona con batería, experimentará esta interferencia cuando esté lo suficientemente cerca de una fuente de red);
  • Fuentes de RF cercanas a la frecuencia resonante de un rastro en la placa de circuito, o uno de sus armónicos;
  • Enrutamiento de trazas de alta corriente en la placa de circuito cerca de líneas de señal;
  • Etc.

Además (como mencionó @jippie), el sesgo del reloj es una causa muy común de errores en cualquier tipo de comunicación en serie que utiliza una velocidad de datos predeterminada. Si está utilizando un cristal externo e interactuando con otro sistema que razonablemente puede esperarse que sea preciso, es menos probable que cause problemas. Sin embargo, los osciladores internos pueden tener tolerancias que son varios órdenes de magnitud peores que los cristales, y tienden a variar más en los rangos de temperatura.

Hay varias pruebas básicas que se pueden realizar en un sistema en ejecución para determinar la inmunidad básica al ruido (y sesgo) de su interfaz, que incluyen:

  • Congelación (enfriar el circuito a la clasificación mínima de sus componentes);
  • Hornear (calentar al máximo);
  • Exposición a EMI :
    • Coloque la placa encima del cable de alimentación de un calentador de espacio en funcionamiento;
    • Clave una radio CB en las proximidades de la placa;
    • Coloque la placa junto a su enrutador inalámbrico;
    • Utilice un cable de conexión largo (en lugar de un cable serie construido adecuadamente) para la conexión UART.

Hay muchos otros, de hecho, hay grandes laboratorios de pruebas dedicados a la calificación EMC .

En general, a menos que sea aceptable un nivel mínimo de pérdida de datos, siempre es prudente incluir algún tipo de verificación de errores en su código de comunicaciones. Incluso una simple suma de control es mejor que nada.

Scott Winder
fuente
6

Una fuente común de errores en UART además de la calidad del nivel de señal (ruido, tiempos de subida / bajada) es la inclinación del reloj. Si el reloj del transmisor y el reloj del receptor no se derivan de la misma fuente (que es el caso la mayor parte del tiempo), uno funcionará más rápido que el otro. Cuando el error de tiempo es demasiado grande, ocasionalmente puede leer un bit incorrecto.

jippie
fuente
¿Qué haría que el reloj se torciera si el microcontrolador se quedara solo en una caja negra, en medio de quién sabe dónde?
user791953
1
Relojes locales de funcionamiento libre. Cada oscilador tiene su propia precisión. El reloj MCU se puede dividir a una frecuencia utilizable para UART, pero a veces está apagado en un pequeño porcentaje. Esto a su vez es causado por el hecho de que el divisor es un número entero.
jippie
P.ej. Reloj MCU = 16MHz, velocidad de transmisión UART = 9600Bd. Entonces, el UART se registra comúnmente con 153600Hz. Pero 16000000/153600 no es un número entero, por lo que la velocidad en baudios estará desactivada.
jippie
Correcto, eso dará un pequeño porcentaje de error. Supongo que he tenido la suerte de no haber encontrado ningún error, pero si se trata de datos críticos, las verificaciones deben hacerse siempre.
user791953
Baja velocidad de transmisión, mayor velocidad de reloj (aumenta la resolución de muestreo y la precisión de sincronización).
jippie
1

La mayoría de los errores provienen de tres causas: (1) la señal generada por el transmisor no representaba datos válidos; (2) la señal del transmisor no se recibió como se generó, o (3) el receptor no estaba listo para manejar los datos cuando se recibió. La causa más común que he visto para el problema n. ° 1 es un transmisor que se reconfigura o apaga mientras transmite datos. El problema # 2 puede ocurrir fácilmente para las señales que viajan a través del "mundo exterior" como resultado de cosas como la interferencia de radio (¡los teléfonos móviles pueden ser sorprendentemente desagradables!), Pero generalmente no debería ocurrir para las señales confinadas en una sola placa. El problema n. ° 3 puede ocurrir porque muchos bytes llegan más rápido de lo que pueden procesarse o porque el receptor se reconfigura, apaga o inicia durante una transmisión.

En muchos casos, es difícil eliminar por completo todos estos problemas; El objetivo de uno debería ser asegurar que el "daño" total hecho por ellos (probabilidad de ocurrencia, multiplicado por daño por ocurrencia) sea aceptablemente bajo. Esto se puede hacer más fácilmente eligiendo una estimación pesimista de confiabilidad y luego diseñando un protocolo para que el impacto en el rendimiento del sistema de incluso las peores fallas que sean consistentes con las estimaciones de uno esté dentro de límites aceptables.

Super gato
fuente
0

Los errores de trama pueden ser causados ​​por lo que @jippie menciona: el receptor ha detectado el bit de inicio y, cuando espera el bit de parada, los datos se invierten. Esto también puede deberse a la corrupción de datos causada por la interferencia de línea que afecta el bit de parada. Siempre debe verificar esto para cada byte recibido.

Los errores de paridad se producen cuando se implementa la paridad en el enlace de datos y hay una corrupción que provoca una discrepancia de paridad en los datos recibidos. Siempre debe verificar esto para cada byte recibido.

La interrupción de recepción también se considera un error, aunque en realidad es una indicación de que los datos entrantes han caído a cero lógico durante más de 1 byte de datos. Normalmente 1 lógico es el estado "ambiente" entre los bytes de datos sucesivos y permanece así. Es un retroceso a los viejos sistemas de telegrafía, creo. No me molestaría en verificar esto a menos que esté utilizando esta "función" para indicar (por ejemplo) un comando de reinicio al receptor.

El error de desbordamiento es cuando se recibe un nuevo byte antes de que una CPU leyera el byte anterior. Ligeramente diferente cuando se trata de un FIFO pero equivale a lo mismo: los datos recibidos válidos se pierden debido a la lentitud de la CPU. Siempre verifique esto antes de leer un byte y si el byte es parte de un mensaje (o comando) más largo, deseche todo el mensaje / comando y solicite al transmisor que vuelva a enviar el mensaje / comando completo.

En ejecución no es realmente un error, pero indica al UART emisor que su búfer de transmisión está vacío, es decir, está solicitando un nuevo byte para transmitir. No necesita verificar esto.

Andy alias
fuente
Entiendo cuáles son estos errores y por qué ocurren, mi pregunta es más detallada sobre cuándo debería proporcionarse una verificación de errores.
user791953
@ user791953 - hecho
Andy, también conocido el
Por cierto, el underrun no es un problema con la mayoría de los protocolos, pero algunos protocolos usan una línea inactiva para indicar el final del paquete. En tales casos, una subestimación en el lado de transmisión puede hacer que el receptor piense incorrectamente que el paquete finaliza antes de lo que se supone que debe hacer.
supercat
0

Para hacer frente a estos errores, debe implementar un protocolo lógico de nivel superior. algo parecido a TCP, o consulte la pila OSI para obtener ideas.

básicamente, dos partes importantes para comenzar son las sumas de verificación y los tiempos de espera. use un algoritmo para calcular un valor redundante que represente, en una forma más pequeña, el contenido de cada mensaje. luego verifique esto en el mensaje recibido. si las sumas no coinciden, es posible que haya recibido un error de trama, ruido de bits, etc., y deberá descartar el mensaje e intentar algún tipo de recuperación, reenvío, señal NACK (no confirmada), etc.

Además, asegúrese de implementar tiempos de espera en su protocolo de nivel superior. Si obtiene algún tipo de error de trama, es posible que su UART nunca se recupere y comience a procesar nuevamente. puede estar esperando el bit de detención en una trama que el remitente UART cree que ya se envió, pero que se corrompió por ruido, distorsión del reloj, etc. Esto enviará cualquier código de entrada a un bucle infinito. asegúrese de tener un límite sensato en cuanto a cuánto tiempo debe esperar su lectura de entrada hasta que decida abandonar este mensaje, y nuevamente, vuelva a intentar, NACK, abandone, etc.

Andyz Smith
fuente
Los tiempos de espera deben implementarse en al menos un lado de cualquier protocolo de nivel superior; En muchos casos, es mejor implementarlos exactamente en un lado. Tener un lado esperando por siempre datos que nunca llegan es solo un problema si hay algo más útil que podría haber estado haciendo en su lugar. Si X le pide a Y algunos datos, X deberá estar preparado para reenviar su solicitud en caso de que Y no la reciba. Y, sin embargo, no tendrá que preocuparse por si X obtiene su respuesta. Si X no lo obtiene, X solicitará nuevamente los datos. El hecho de que X no vuelva a pedir los datos significa que Y no necesita reenviarlos.
supercat
@supercat bien, este es un buen patrón, pero estoy apuntando más hacia la codificación de línea por línea de bajo nivel. siempre tendrá un bucle que lee datos e intenta averiguar si un mensaje completo está listo, si un mensaje completo nunca está allí, puede colgar el subsistema de entrada, independientemente de si no hay nada más que esperar hecho. en este caso, el subsistema de entrada necesita al menos darse cuenta de que se produjo una falla, vaciar los datos de gabage y reiniciarse para otro intento.
Andyz Smith
Si cada paquete comienza con una secuencia de bytes que siempre es identificable en cualquier contexto, y si el receptor no tiene nada útil que pueda hacer hasta que reciba un paquete completo, ¿por qué debería importar si transcurren algunas horas después de recibir un paquete parcial? La próxima vez que alguien intente enviar un paquete real, el receptor verá el marcador de inicio del paquete y abandonará el paquete parcial.
supercat
@supercat porque entonces tienes un bucle que busca múltiples cosas. todavía está buscando el final del paquete parcial, y está buscando el comienzo de un paquete nuevo y sin corrupción. esto hace que la lógica sea mucho más compleja en términos de codificación práctica, si es así, do while.
Andyz Smith
No estoy muy seguro de cuál es la dificultad. Si uno está usando un bucle de recepción de bytes, tendrá que salir de él si se produce un tiempo de espera o si se ve un byte de inicio. Ambos comportamientos deben manejarse de manera idéntica, salvo solo por el hecho de que la secuencia de inicio debe establecer un indicador, por lo que el siguiente código que lo busque no molestará.
Supercat