O que causa erros de UART?

8

Gostaria de saber por que os erros do UART ocorrem e quando devemos verificar esses erros. Há um post aqui que pergunta sobre como lidar com erros individuais, como saturação, paridade, etc. Eu estou claro sobre o porquê da saturação de dados, por que ocorre o erro de paridade, mas eu gostaria de saber qual é a causa raiz. Minha pergunta é mais focada em por que esses erros podem ocorrer (razões físicas) e quando se deve fazer a verificação de erros como um fator para sua aplicação.

Até agora, meu programa parece funcionar muito bem (sem verificação de erro), mas sei que o ruído pode atrapalhar as coisas. Como simular condições que podem causar falhas nas portas UART Rx / Tx?

user791953
fonte

Respostas:

8

Existem várias fontes potenciais de ruído em qualquer circuito. Alguns dos mais comuns incluem:

  • Fontes de alimentação mal reguladas;
  • Comutação de fontes de alimentação;
  • Desacoplamento capacitivo insuficiente dos trilhos de energia próximos ao MCU;
  • Acoplamento indutivo de fontes eletromagnéticas próximas (incluindo 50 ou 60Hz da energia da rede elétrica; mesmo se o circuito for alimentado por bateria, ele sofrerá essa interferência quando estiver próximo o suficiente de uma fonte de energia elétrica);
  • Fontes de RF próximas à frequência ressonante de um traço na placa de circuito ou em um de seus harmônicos;
  • Roteamento de traços de alta corrente na placa de circuito próximo às linhas de sinal;
  • Etc.

Além disso (como @jippie mencionou), a inclinação do relógio é uma causa muito comum de erros em qualquer tipo de comunicação serial que usa uma taxa de dados predeterminada. Se você estiver usando um cristal externo e fazendo interface com outro sistema que possa ser razoavelmente preciso, é menos provável que cause problemas. Os osciladores internos, no entanto, podem ter tolerâncias que são várias ordens de magnitude piores que os cristais e tendem a variar mais em faixas de temperatura.

Existem vários testes básicos que podem ser executados em um sistema em execução para determinar a imunidade básica a ruídos (e distorção) da sua interface, incluindo:

  • Congelamento (resfrie o circuito até a classificação mínima de seus componentes);
  • Cozimento (aqueça até a classificação máxima);
  • Exposição ao IME :
    • Coloque a placa em cima do cabo de alimentação de um aquecedor de ambiente;
    • Tecle um rádio CB nas proximidades do quadro;
    • Coloque a placa ao lado do seu roteador sem fio;
    • Use fio de conexão longo (em vez de um cabo serial adequadamente construído) para a conexão UART.

Existem muitos outros - na verdade, existem grandes laboratórios de testes dedicados à qualificação EMC .

Em geral, a menos que seja aceitável um nível mínimo de perda de dados, é sempre prudente incluir algum tipo de verificação de erro no seu código de comunicação. Mesmo uma simples soma de verificação é melhor que nada.

Scott Winder
fonte
6

Uma fonte comum de erros no UART além da qualidade do nível de sinal (ruído, tempos de subida / descida) é a inclinação do relógio. Se o relógio do transmissor e do receptor não forem derivados da mesma fonte (que é o caso na maioria das vezes), um funcionará mais rápido que o outro. Quando o erro de temporização é muito grande, você pode ocasionalmente ler um bit errado.

jippie
fonte
O que faria o relógio se inclinar se o microcontrolador fosse deixado sozinho em uma caixa preta, no meio de quem sabe onde?
user791953
1
Relógios locais com funcionamento gratuito. Todo oscilador tem sua própria precisão. O relógio do MCU pode ser dividido em uma frequência utilizável para o UART, mas às vezes é desativado por uma pequena porcentagem. Por sua vez, isso é causado pelo fato de o divisor ser um número inteiro.
jippie
Por exemplo. Clock do MCU = 16MHz, taxa de transmissão UART = 9600Bd. Em seguida, o UART geralmente possui clock de 153600Hz. Mas 16000000/153600 não é um número inteiro, portanto a taxa de transmissão estará desativada.
jippie
Certo, isso dará uma pequena porcentagem de erro. Acho que tive a sorte de não encontrar nenhum erro, mas se forem dados críticos, as verificações devem ser feitas sempre.
user791953
Taxa de transmissão mais baixa, taxa de clock mais alta (aumenta a resolução da amostra e a precisão do tempo).
jippie
1

A maioria dos erros resulta de três causas: (1) o sinal gerado pelo transmissor não representa dados válidos; (2) o sinal do transmissor não foi recebido como gerado ou (3) o receptor não estava pronto para manipular os dados quando foram recebidos. A causa mais comum que vi para o problema nº 1 é um transmissor que é reconfigurado ou desligado enquanto transmite dados. O problema 2 pode ocorrer facilmente para sinais que viajam pelo "mundo exterior" como resultado de interferências de rádio (telefones celulares podem ser surpreendentemente desagradáveis!), Mas geralmente não deve ocorrer para sinais confinados a uma única placa. O problema nº 3 pode ocorrer porque muitos bytes chegam mais rapidamente do que podem ser processados ​​ou porque o receptor é reconfigurado, desligado ou inicializado durante uma transmissão.

Em muitos casos, é difícil eliminar completamente todos esses problemas; o objetivo de alguém deve ser garantir que o "dano" total causado por eles (probabilidade de ocorrência, vezes o dano por ocorrência) seja aceitávelmente baixo. Isso pode ser feito com mais facilidade, escolhendo uma estimativa pessimista de confiabilidade e, em seguida, projetando um protocolo para que o impacto no desempenho do sistema, mesmo nas piores falhas que eram consistentes com as estimativas, estivesse dentro de limites aceitáveis.

supercat
fonte
0

Erros de enquadramento podem ser causados ​​pelo que o @jippie menciona - o receptor detectou o bit de início e onde espera o bit de parada, os dados são invertidos. Isso também pode ocorrer devido à corrupção de dados causada pela interferência da linha no bit de parada. Você sempre precisa verificar isso para cada byte recebido.

Erros de paridade ocorrem quando a paridade é implementada no link de dados e há uma corrupção que causa uma incompatibilidade de paridade nos dados recebidos. Você sempre precisa verificar isso para cada byte recebido.

A interrupção de recebimento também é considerada um erro, embora seja realmente uma indicação de que os dados recebidos caíram para zero lógico por mais de 1 byte de dados. Normalmente 1 lógico é o estado "ambiente" entre bytes de dados sucessivos e permanece assim. É um retorno aos velhos sistemas de telegrafia, eu acho. Eu não me incomodaria em verificar isso, a menos que você estivesse usando esse "recurso" para indicar (digamos) um comando de redefinição para o receptor.

Erro de saturação é quando um novo byte é recebido antes que o byte anterior seja lido por uma CPU. Um pouco diferente quando um FIFO está envolvido, mas equivale à mesma coisa - dados recebidos válidos são perdidos devido à lentidão da CPU. Sempre verifique isso antes de ler um byte e se o byte faz parte de uma mensagem (ou comando) mais longa, jogue fora toda a mensagem / comando e, de alguma forma, solicite ao transmissor que reenvie toda a mensagem / comando.

Sob execução não é realmente um erro, mas indica ao UART remetente que seu buffer de transmissão está vazio, ou seja, está solicitando um novo byte para transmitir. Você não precisa verificar isso.

Andy aka
fonte
Eu entendo o que são esses erros e por que eles ocorrem. Minha pergunta é mais sobre quando devemos fornecer uma verificação de erros para eles.
user791953
@ user791953 - feito
Andy aka
BTW, underrun não é um problema com a maioria dos protocolos, mas alguns protocolos usam uma linha ociosa para indicar o fim do pacote. Nesses casos, uma falha no lado da transmissão pode fazer com que o receptor pense incorretamente que o pacote termina antes do esperado.
Supercat 25/09/13
0

Para lidar com esses erros, você deve implementar um protocolo lógico de nível superior. algo semelhante ao TCP ou verifique a pilha OSI para obter idéias.

basicamente, duas partes importantes para começar são somas de verificação e tempos limite. use um algoritmo para calcular um valor redundante que represente, em uma forma menor, o conteúdo de cada mensagem. depois verifique isso na mensagem recebida. se as somas não corresponderem, é possível que você tenha recebido um erro de enquadramento, ruído de bits, etc., etc., e precisará descartar a mensagem e tentar algum tipo de recuperação, reenviar, sinal NACK (não aceito), etc.

Além disso, certifique-se de implementar tempos limite no seu protocolo de nível superior. se você receber algum tipo de erro de enquadramento, seu UART pode nunca se recuperar e começar a processar novamente. pode estar aguardando o bit de parada em um quadro que o remetente que o UART acha que já foi enviado, mas foi corrompido por ruído, inclinação do relógio, etc. isso enviará qualquer código de entrada para um loop infinito. verifique se você tem um limite sensato de quanto tempo sua leitura de entrada deve esperar até decidir abandonar esta mensagem e, novamente, tente novamente, NACK, abandonar etc.

Andyz Smith
fonte
Os tempos limite precisam ser implementados em pelo menos um lado de qualquer protocolo de nível superior; em muitos casos, é melhor implementá-los exatamente de um lado. Ter um lado esperando eternamente por dados que nunca chegam é apenas um problema se houver algo mais útil que poderia estar fazendo. Se X solicitar alguns dados a Y, X precisará estar preparado para reenviar sua solicitação, caso Y não a receba. Y, no entanto, não precisará se preocupar se X recebe sua resposta. Se o X não conseguir, o X solicitará os dados novamente. O fato de X não pedir novamente os dados significa que Y não precisa reenviá-lo.
Supercat
@ Supercat certo, este é um bom padrão, mas estou visando mais o nível baixo de linha por linha de codificação. você sempre terá um loop que está lendo dados e tentando descobrir se uma mensagem completa está pronta, se uma mensagem completa nunca estiver lá, ele pode travar o subsistema de entrada, independentemente se não houver mais nada além de esperar para ser feito. nesse caso, o subsistema de entrada precisa pelo menos perceber que ocorreu uma falha, liberar quaisquer dados de gabarito e redefinir para outra tentativa.
Andyz Smith
Se cada pacote começa com uma sequência de bytes que é sempre identificável em qualquer contexto, e se o receptor não tem nada útil, ele pode fazer até receber um pacote completo, por que deveria se importar se algumas horas decorrem depois de receber um pacote parcial? Na próxima vez que alguém tentar enviar um pacote real, o destinatário verá o marcador de início de pacote e abandonará o pacote parcial.
Supercat 25/09/13
@ supercat porque então você tem um loop que está procurando várias coisas. ele ainda está procurando o fim do pacote parcial e está procurando o início de um pacote novo e não corrompido. isso torna a lógica muito mais complexa em termos de codificação prática, se for o caso, durante o processo.
Andyz Smith
Não sei bem qual é a dificuldade. Se alguém estiver usando um loop de recebimento de bytes, será necessário interromper o processo se ocorrer um tempo limite ou se for visto um byte inicial. Ambos os comportamentos precisam ser tratados de forma idêntica, exceto apenas pelo fato de que a sequência de início deve definir um sinalizador, para que o próximo código que o procure não o incomode.
Supercat 25/09/13