web-dev-qa-db-ja.com

シリアルポートのバッファをクリアする

これは、シリアルポートを開くための私の関数の外観です(Ubuntu 12.04を使用)。

_int open_port(void)
{
  int fd; /* File descriptor for the port */

  fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

  if (fd == -1)
  {
   // Could not open the port.          
   perror("open_port: Unable to open /dev/ttyUSB0 - ");
  }
  else
    fcntl(fd, F_SETFL, 0);

  struct termios options;

  tcgetattr(fd, &options); 
  //setting baud rates and stuff
  cfsetispeed(&options, B19200);
  cfsetospeed(&options, B19200);
  options.c_cflag |= (CLOCAL | CREAD);
  tcsetattr(fd, TCSANOW, &options);

  tcsetattr(fd, TCSAFLUSH, &options);

  options.c_cflag &= ~PARENB;//next 4 lines setting 8N1
  options.c_cflag &= ~CSTOPB;
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= CS8;

  //options.c_cflag &= ~CNEW_RTSCTS;

  options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //raw input

  options.c_iflag &= ~(IXON | IXOFF | IXANY); //disable software flow control

  return (fd);
}
_

問題は、このプログラムを実行すると、シリアルデバイスが既に接続されている場合、バッファーにコンテンツが含まれていることです。読み取りを開始する前にバッファをクリアする方法が必要です。 tcsetattr(fd, TCSAFLUSH, &options);を使用すると、ポートを初期化する前にIOバッファをフラッシュすることでこの問題を解決できると思いますが、そのような運はありません。洞察はありますか?

17
capcom

私はそれを理解したと思います。何らかの理由で、フラッシュする前に遅延を追加する必要があります。トリックを実行するために、fdseemを返す前に追加された次の2行:

  sleep(2); //required to make flush work, for some reason
  tcflush(fd,TCIOFLUSH);
25
capcom

この問題の原因は、USBシリアルポートの使用にあります。通常のシリアルポートを使用する場合、この問題は発生しません。

ほとんどのUSBシリアルポートドライバーは正しくフラッシュをサポートしていません。おそらく内部シフトレジスタ、FIFOまたはUSBサブシステムにデータがまだあるかどうかを知る方法がないためです。

以前に報告された同様の問題に対するGregの回答 here も参照してください。

あなたのsleepは問題を解決するかもしれませんが、それは回避策にすぎません。残念ながら、通常のシリアルポートを使用する以外に解決策はありません。

6
Robert

Open()でリセットされるArduino Unoボードでも同様の症状が発生しています。 Arduinoボードがリセットされる前、つまりopen()が呼び出される前に生成されたopen()呼び出しの後にデータを受信して​​いました。

Ioctl()呼び出しによる問題の追跡私は、tcflush()が呼び出されるまでにデータがまだ入力バッファーに到着していないことを知りました。したがって、tcflush()は機能しましたが、フラッシュするデータはありませんでした。 open()呼び出し後の1000 usのスリープで問題が解決したようです。これは、tcflush()が呼び出される前にデータの到着を許可したため、tcflush()が実際に入力バッファーをフラッシュしたためです。

同じ問題が発生している可能性があります。

5
areslagae