10

したがって、USBシリアルポートを介して「HELLO」を送信する次のテストコードがあります。

int fd;
struct termios tty;

if((fd = open("/dev/ttyUSB0", O_WRONLY|O_NONBLOCK|O_NOCTTY)) == -1){
err(1, "Cannot open write on /dev/ttyUSB0");
}

tcgetattr(fd, &tty);
tty.c_iflag = 0;
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_cflag = 0;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 0;
cfsetospeed(&tty, B19200);
cfsetispeed(&tty, B19200);
tty.c_cflag |= CREAD|CRTSCTS|HUPCL|CS8;
tcsetattr(fd, TCSANOW, &tty);

printf("Write: %i\n", write(fd, "HELLO", 5));

sleep(5);

if(close(fd) != 0){
warn("Could not close write fd");
}

プログラムは正常に実行され、"HELLO" が送信されますが、問題が 1 つあります。「HELLO」は、write() 関数が呼び出されたときに送信されるのではなく、ファイル記述子が閉じられたときに送信されるようです。この理論をテストするために上に sleep(5) 行を追加しましたが、確かに、プログラムが実行されてから 5 秒後に「HELLO」が送信されます。close() コマンドの代わりに write() コマンドの直後に「HELLO」を送信するにはどうすればよいですか?

4

8 に答える 8

8

デバイスは tty デバイスなので、fsync は役に立ちません。おそらくフラッシュもしないでしょう。

デフォルトでは、デバイスは正規モードで動作しています。つまり、データは行単位でパッケージ化されます。おそらく、データに cr/lf ペアを追加すると、データが送信されることに気付くでしょう。

標準モードがオフになっていることを確認する必要があります。また、Rの答えが役に立ちます。

http://en.wikibooks.org/wiki/Serial_Programming/termios

于 2010-07-12T14:21:45.613 に答える
6

のマニュアルページからwrite()

write()からの正常な復帰は、データがディスクにコミットされたことを保証するものではありません。実際、一部のバグのある実装では、データ用にスペースが正常に予約されていることを保証することすらできません。確実にする唯一の方法は、すべてのデータの書き込みが完了した後でfsync(2)を呼び出すことです。

fsync()データが実際にコミットされていることを確認するには、ファイル記述子を呼び出す必要があります。

于 2010-07-12T12:58:56.103 に答える
3

まず第一に、最初にすべての termios フィールドを 0 に設定した理由がわかりません。その後、その前の 0 を変更せずに、cflag に通常の rs232 フラグを設定することにしました。(ORを直接使用せずに、上記の0に設定するのではなく)。

これらすべてのフラグを設定する代わりに、termios フィールドを cfmakeraw() で設定するだけです。

また、sync(); パラメーターなし (NOT fsync! ;) は、ブロック デバイスだけでなく、すべての保留中の出力をすべてのファイル記述子に送信するようです。また、tcp ソケットと rs232..

また、open() にはオプション O_SYNC があります (O_SYNC と O_ASYNC は紛らわしい名前を持っていますが、シリアル ライン プロトコルがクロックされているかどうかとは関係ありません。一方はすぐに write() をコミットし、もう一方は入力時にトラップするためのシグナルを生成します。利用可能になります (dos の irq ベースの rs232 のようなものです ;)

open() で O_SYNC を設定すると、すでに問題が解決している可能性があります。

また、「反対側のデータを読み取ることによって」...「LED」と「抵抗器」と呼ばれるものがあり、TXD に接続してデータを表示するだけです ;) また、「rs232 ブレークアウト ボックス」またはそれを直接見え​​るようにすることができるスコープ ;) どちらの側が適切に動作していないかを「推測」するよりもはるかに簡単です。

警告: コードはテストしていません。コンパイルします。しかし、私はすべての ttyUSB0 ケーブルを別の建物に持っています。とにかく、あなたの主な問題は O_SYNC だと思います。すべての termios crap を 0 に設定することは、cfmakeraw() とほとんど同じです... また、書き込み専用で開く場合は、なぜ CREAD を設定するのですか? (とにかく、読み取り書き込みではなく書き込み専用で開くのはなぜですか?-また、書き込み専用の場合、制御tty(O_NOCTTY ;)になることを恐れる必要はありません。したがって、書き込み専用の場合、それも正確には必要ありません.. .

%i (%d btw と同じ) フォーマッタもタイプの不一致をトリガーし、write() の ssize_t 戻り値を (int) にキャストすることを警告することに気付きました

#include<termios.h>
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>

void main(){
int fd;
struct termios tty;
fd=-1;
while(fd<0){fd=open("/dev/ttyUSB0",O_WRONLY|O_NONBLOCK|O_NOCTTY|O_SYNC);sleep(1);};
cfmakeraw(&tty);
tty.c_cflag=CREAD|CRTSCTS|HUPCL|CS8;
cfsetospeed(&tty,B19200);
cfsetispeed(&tty,B19200);
tcsetattr(fd,TCSANOW,&tty);
printf("Write: %i\n",(int)write(fd,"HELLO",5));
sync();//if all else fails, also try without, O_SYNC should already fix that.
close(fd);
};
于 2016-02-02T21:47:16.613 に答える
2

多くの場合、出力ポートはバッファリングされるため、出力ストリームへの書き込みと、実際にディスクや回線などに送信されるコンテンツとの間には、多少のギャップがあります。これは一般的に効率のためです。

バッファを強制的に出力にコミットするには、fflush(3)を参照してください。

バッファリングされないように出力記述子を開くこともできるかもしれませんが、fflush「これで完了です」と言うのがおそらく良いでしょう。

于 2010-07-12T13:02:37.483 に答える
0

この行を変更します。

tty.c_cc[VMIN] = 0;

これに:

tty.c_cc[VMIN] = 1;
于 2010-07-12T13:50:10.790 に答える
-1

バッファはフラッシュされません。フラッシュ。

于 2010-07-12T12:58:46.060 に答える
-1

この質問をご覧ください。基本的に、必要なときにIOを実行するには、ファイルをフラッシュする必要があります。

于 2010-07-12T12:59:03.310 に答える
-1

やってみてください

fflush( NULL );

write()。フラッシュされていない内部バッファがあるかもしれません。

于 2010-07-12T12:59:54.150 に答える