O que poderia afetar valores retornados por Serialport.Read ()
-
02-07-2019 - |
Pergunta
Eu escrevi um aplicativo simples em C # 2.0 usando a classe 2.0 serialport .Net Framework para se comunicar com uma placa controladora via COM1.
Um problema ocorreu recentemente foram os bytes retornado pelo método de leitura estão incorretas. Ele voltou a quantidade certa de bytes, apenas os valores estão incorretos. Um aplicativo semelhante escrito em Delphi ainda devolveu os valores corretos embora.
Portmon para registar a actividade sobre a porta serial de ambos os apps, comparou os dois troncos e lá onde algumas configurações (aparentemente) menores diferente e eu tentei a imitar o aplicativo Delphi, tanto quanto possível, mas sem sucesso.
Então, o que poderia afetar os valores de bytes retornados pelo método de leitura?
A maioria das configurações entre os dois aplicativos são idênticos.
Aqui está uma lista das linhas que diferiam no log de Portmon:
Delphi App:
IOCTL_SERIAL_SET_CHAR Serial0 SUCESSO EOF: dc ERR: 0 BRK: 0 EVT: 0 XON: 11 XOFF: 13
IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCESSO Agite: 0 Substituir: 0 XonLimit: 256 XoffLimit: 256 IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCESSO RI: -1RM: 100 RC: 1000WM: 100 WC: Máscara 1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCESSO: RXCHAR RXFLAG TXEMPTY CTS DSR RLSD BRK ERR ANEL RX80FULL
C # App:
IOCTL_SERIAL_SET_CHAR Serial0 SUCESSO EOF: 1a ERR: 0 BRK: 0 EVT: 1a XON: 11 XOFF: 13 IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCESSO Agite: 0 Substituir: 0 XonLimit: 1024 XoffLimit: 1024 IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCESSO RI: -1
RM: -1 RC: 1000WM: 0 WC: Máscara 1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCESSO: RXCHAR RXFLAG CTS DSR RLSD BRK ERR ANEL
UPDATE:
Os bytes retornados corretas foram: 91, 1, 1, 3, 48, 48, 50, 69, 66, 51, 70, 55, 52, 93 (14 bytes). O último valor de ser um simples checksum.
Os valores incorrectos devolvidos foram:. 91, 241, 254, 252, 242, 146, 42, 201, 51, 70, 55, 52, 93 (13 bytes)
Como você pode ver o primeiro eo último cinco bytes retornado correspondem.
O evento ErrorReceived indica que ocorreu um erro de enquadramento, o que poderia explicar os valores incorretos. Mas a questão é por que SerialPort encontrar um erro de enquadramento quando o aplicativo Delphi, aparentemente, não faz?
Solução
Bem, parece como se o problema foi resolvido (pelo menos por enquanto).
Aparentemente, um erro de enquadramento causado o retorno de valores incorretos. Eu escrevi um aplicativo VB6, usando o controle MSComm, que funcionou bem, e comparou os arquivos de log gerados pelo Portmon.
Eu peguei as seguintes diferenças
VB6 App:
IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCESSO Agite: 1 Substituir: 0 XonLimit: 256 XoffLimit: 256
C # App:
IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCESSO Agite: 0 Substituir: 0 XonLimit: 1024 XoffLimit: 1024
Brincando com as configurações que eu descobri que se eu set
_serialPort.DtrEnable = true
o C # App gera a seguinte entrada de log:
IOCTL_SERIAL_SET_HANDFLOW Serial0 SUCESSO Agite: 1 Substituir: 0 XonLimit: 1024 XoffLimit: 1024
Isso pareceu impedir que o erro de enquadramento eo aplicativo parece estar funcionando bem.
Outras dicas
Você verificou as definições para o número de bits de dados, bits de parada e paridade?
O bit de paridade é uma espécie de mecanismo de detecção de erros. Por exemplo: Se você enviar usando 7 bits de dados e um bit de paridade, o oitavo bit será usado para a detecção de erros de bit de inversão. Se o receptor espera 8 bits de dados e sem bits de paridade, o resultado será truncado.
Infelizmente você não mencionou exatamente que tipo de diferenças que você começa. É um caráter ocasional que é diferente ou se todos os seus dados de entrada truncado? Note que caracteres lidos através da função SerialPort.Read poderia ser alterado pelo sistema devido à configuração do SerialPort.Encoding propriedade . Esta definição afecta a interpretação do texto de entrada como era de texto em ASCII, Unicode, UTF-8 ou qualquer outro esquema de codificação do Windows usa para 'byte-prima (s)' à conversão 'texto legível'.
Se você está lendo em uma matriz de bytes (ex: SerialPort.Read). Você deve obter exatamente os bytes que você está vendo na Portmon
Se você estiver convertendo para caracteres (SerialPort.ReadLine ou SerialPort.ReadChar), em seguida, os dados serão codificados usando a codificação atual (propriedade SerialPort.Encoding), o que explica as diferenças que você está vendo.
Se você quiser ver personagens com os mesmos valores binários como os bytes sobre o fio, uma boa codificação para uso é Latin-1 como descrito em este post .
Exemplo:
SerialPort.Encoding = Encoding.GetEncoding("Latin1")