全二重シリアルラインを介してI / Oを実行したいアプリケーションがあります。それは:
char buf[4];
write(fd, "ping", 4);
read(fd, buf, 4);
...リモートデバイスが「ping」文字列に応答して送信する4バイトで終わると予想されます。
しかし、私は半二重RS485ラインを使用しているので、シリアルラインで送信されたすべてのバイトはシリアルラインでも受信されます。はい同じ行)。したがって、上記のコードスニペットは、リモートデバイスが何でも送信する前に常に「ping」をバッファに読み込みます。
明らかに、ホストコードはこれを期待していませんでした。
私が思いついた最善の解決策は、常に書き込んだ後に読み書きした文字が送信された文字と一致することを確認して無視することです。
しかし、もっと良い方法がありますか?送信中に文字の受信を抑制する信頼できるUnixイディオムはありますか?
(私の質問には多くの微妙さと小さな紆余曲折があることに感謝します。たとえば、UARTにFIFOがありますか?受信プロセスは同じスレッドで実行されますか?など)。
修正する
write()
私は各バイトの後に同じ数のread()
バイトを呼び出し、それを使用して一致することをstrncmp()
確認する簡単なルーチンを実装しました。強力に見えますが、ドライバーレベルでより良い方法、または少なくとも他の方法があるかどうかを知りたいです。
答え1
実用的に言えば、現在持っているものが機能しているようで、設定を変更したくない場合、またはこれがワンタイムハッキングの場合は、引き続きソリューションを使用してください。
しかし、LinuxにはAPIがありますRS485正しいハードウェアを見つけるために試してみてください。一部のハードウェアには、シリアルポートが適切な状態にあるときに動作する半二重モードが組み込まれています。たとえば、ioctl は RS485 モードをイネーブルにするために使用されます。
#include <linux/serial.h>
struct serial_rs485 rs485conf = {0};
rs485conf.flags |= SER_RS485_ENABLED;
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) ...
または、転送時にRTSピンのロジックレベルを1に設定します。
rs485conf.flags |= SER_RS485_RTS_ON_SEND;