Como inibir a recepção serial durante gravações em série para uma linha serial RS485 (half-duplex)

1

Eu tenho um aplicativo que espera fazer E / S em uma linha serial full-duplex. Isso é:

char buf[4];
write(fd, "ping", 4);
read(fd, buf, 4);

... espera acabar com os quatro bytes que o dispositivo remoto transmitiu em resposta à string "ping".

Mas estou rodando em uma linha RS485 half-duplex, então cada byte que é transmitido na linha serial também é recebido na linha serial (porque são a mesma linha) . Portanto, o trecho de código acima sempre lê "ping" no buffer antes que o dispositivo remoto transmita qualquer coisa.

Obviamente, o código do host não está esperando isso.

A melhor solução que obtenho é sempre ler depois de escrever e verificar se os caracteres recebidos correspondem aos que foram enviados e depois ignorá-los.

Mas existe uma maneira melhor? Existe um idioma confiável do Unix para inibir a recepção de caracteres durante o tempo em que os caracteres estão sendo transmitidos?

(Eu aprecio que há muitas sutilezas e pequenos labirintos em minha pergunta. Por exemplo, a UART tem um fifo? O processo de recebimento está sendo executado no mesmo segmento? Etc. Se fosse fácil, eu não faria isso?) t estar pedindo unix.stackexchange!:)

atualizar

Eu implementei uma rotina simples que chamo depois de cada write() a read() um equivalente de bytes e depois uso strncmp() para verificar se eles correspondem. Parece ser robusto, mas ainda estou interessado em saber se existe uma abordagem de nível de driver que pode fazer isso melhor, ou pelo menos de forma diferente.

    
por fearless_fool 08.10.2017 / 03:33

1 resposta

2

Pragmaticamente, se o que você tem parece funcionar, e você não está esperando nenhuma mudança na configuração, ou se é uma invasão única, então fique com a sua solução.

No entanto, o Linux tem uma API para rs485 hardware apropriado, que você pode tentar. Alguns hardwares possuem um modo half-duplex integrado que funcionará se você colocar a porta serial no estado apropriado. Os ioctls são, por exemplo, para ativar o modo RS485:

#include <linux/serial.h>
struct serial_rs485 rs485conf = {0};
rs485conf.flags |= SER_RS485_ENABLED;
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) ...

ou defina o nível lógico para o pino RTS igual a 1 ao enviar:

rs485conf.flags |= SER_RS485_RTS_ON_SEND;
    
por 08.10.2017 / 19:35