私はFTDIを使用してUSBポート経由でデータを送受信しようとしているので、C/C++を使用してシリアル通信を処理する必要があります。私はのLinux(Ubuntu)で作業しています。Linux Cシリアルポート読み書き
基本的には、受信したコマンドを受信しているデバイスに接続しています。私はそれらのコマンドを送信し、デバイスの応答を読み取る必要があります。両方のコマンドと応答はASCII文字です。
GtkTermを使ってすべてうまく動作しますが、Cプログラミングに切り替えると問題が発生します。
は、ここに私のコードです:
#include <stdio.h> // standard input/output functions
#include <stdlib.h>
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
/* Open File Descriptor */
int USB = open("/dev/ttyUSB0", O_RDWR| O_NONBLOCK | O_NDELAY);
/* Error Handling */
if (USB < 0)
{
cout << "Error " << errno << " opening " << "/dev/ttyUSB0" << ": " << strerror (errno) << endl;
}
/* *** Configure Port *** */
struct termios tty;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if (tcgetattr (USB, &tty) != 0)
{
cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << endl;
}
/* Set Baud Rate */
cfsetospeed (&tty, B9600);
cfsetispeed (&tty, B9600);
/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_lflag = 0; // no signaling chars, no echo, no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
tty.c_iflag &= ~(IXON | IXOFF | IXANY);// turn off s/w flow ctrl
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
tty.c_oflag &= ~OPOST; // make raw
/* Flush Port, then applies attributes */
tcflush(USB, TCIFLUSH);
if (tcsetattr (USB, TCSANOW, &tty) != 0)
{
cout << "Error " << errno << " from tcsetattr" << endl;
}
/* *** WRITE *** */
unsigned char cmd[] = {'I', 'N', 'I', 'T', ' ', '\r', '\0'};
int n_written = write(USB, cmd, sizeof(cmd) -1);
/* Allocate memory for read buffer */
char buf [256];
memset (&buf, '\0', sizeof buf);
/* *** READ *** */
int n = read(USB, &buf , sizeof buf);
/* Error Handling */
if (n < 0)
{
cout << "Error reading: " << strerror(errno) << endl;
}
/* Print what I read... */
cout << "Read: " << buf << endl;
close(USB);
何が起こるかというとread()
戻り0(バイトが全く読まない)、またはブロックタイムアウト(VTIME
)までということです。 write()
は何も送信しないので、私はこれが起こっていると仮定しています。その場合、デバイスはコマンドを受信せず、応答を受け取ることができません。実際には、私のプログラムが読書でブロックされている間にデバイスをオフにすると、実際に応答が得られます(デバイスはシャットダウン中に何かを送信します)。
奇妙なことは、右write()
呼び出した後、この
cout << "I've written: " << n_written << "bytes" << endl;
を追加していることを、私が受け取る:
I've written 6 bytes
私が期待して正確に何です。 のように私のプログラムだけが動作しません。実際に私のデバイスはポートにを書き込むことができません。
私は異なるタイプのデータ型についても試しましたが(実際には何もしませんでしたが、cmd = "INIT \r"
やconst char
などのstd :: stringを使ってみました)
誰かが私が間違っている場所を教えてもらえますか?
ありがとうございます。
EDIT:このコードの 以前バージョン
unsigned char cmd[] = "INIT \n"
またcmd[] = "INIT \r\n"
を用います。デバイスのコマンドシンタクスが
<command><SPACE><CR>
と報告されたため、私はそれを変更しました。
私はまた、読んでO_NONBLOCK
フラグを避けようとしましたが、私は永遠にしかブロックしません。私はselect()
を使ってみましたが、何も起こりません。試してみると、データが利用可能になるまで待機ループを作成しましたが、コードがループを終了することはありません。 Btw、またはusleep()
が私が避ける必要があるものです。報告されたのは自分のコードの抜粋だけです。 完全なコードはリアルタイム環境(特にOROCOS)で動作する必要がありますので、私は本当にスリープのような機能を望んでいません。
あなたの行 'response.append(&buf);'は私のためにはコンパイルされません) 'while(buf!= '\ r' && n> 0);'これらのタイプミスや何か不足していますか? – josaphatv
'int n_written = write(USB、cmd、sizeof(cmd)-1)'を送信することは大容量のバッファではうまくいきません。その場合、上記のようなループが必要ですが、 'n_written – Fritz
'cfmakeraw()'はすでにたくさんの属性を設定していますが、あなたはループを終了させるために長さを使用する必要があります。これらの行は必要ありません: 'tty.c_cflag&=〜CSIZE; tty.c_cflag | = CS8; tty.c_cflag&=〜PARENB;' – rumpel