2016-12-28 5 views
0

デバイスモードではラズベリーPiゼロを使用し、ホストモードではラズベリーパイBを使用しています。私は2つをUSBケーブルで接続しています。今私の目標は、単純な任意のデータを2つのPiの間で行き来させることです。シリアルポートからの読み込みは常に書き込まれた内容を返します

問題は、シリアルポートに書き込んだPiが最初に書き込んだ内容を読み終えてしまうことです。私が書いたプログラムは、デバイスにd\nを送り、ホストはh\nを送ります。したがって、デバイスが最初に書き込む場合、ホストはd\nを正しく読み込み、次にh\nをシリアルポートに書き込みます。しかし、デバイスは、d\nを読み終えます!ホストが最初に書き込むように切り替えると、問題は解決しません。

私は、書き込み後、読み込み前に、さまざまなtcflush呼び出しをプログラムに追加しようとしましたが、動作しません。私はまた、さまざまな時間の睡眠を試みました。私は書かれた文字ごとに100マイクロ秒間待って読んだので、数秒間寝ました。

私のセットアップでは、Pi Zeroの単一のデータ対応USBポートのために、両方のPiの間に一定の接続がないようにする必要があります。テストするために、実際にキーボードを差し込んでプログラムを実行してから、適切なケーブルを差し込んでデータを転送しています。私はデータを転送することはできますが、書き込み後はデータを転送することはできません。

私は私が推測することのできないノブトラップに陥ったと思っています。

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

/* 
* gcc -o device_rw -DDEVICE serial_rw.c 
* gcc -o host_rw serial_rw.c 
*/ 

#define SERIAL_DEVICE "/dev/ttyGS0" 
#define SERIAL_HOST "/dev/ttyACM0" 

#ifdef DEVICE 
#define _TTY SERIAL_DEVICE 
#else 
#define _TTY SERIAL_HOST 
#endif 

int 
set_interface_attribs(int fd, int speed) 
{ 
    struct termios tty; 

    if (tcgetattr(fd, &tty) < 0) { 
     printf("Error from tcgetattr: %s\n", strerror(errno)); 
     return -1; 
    } 

    cfsetospeed(&tty, (speed_t)speed); 
    cfsetispeed(&tty, (speed_t)speed); 

    tty.c_cflag &= ~PARENB;  /* no parity bit */ 
    tty.c_cflag &= ~CSTOPB;  /* only need 1 stop bit */ 
    tty.c_cflag &= ~CSIZE; 
    tty.c_cflag |= CS8;   /* 8-bit characters */ 

    tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */ 
    tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */ 

    tty.c_iflag |= IGNPAR | IGNCR; 
    tty.c_iflag &= ~(IXON | IXOFF | IXANY); 
    tty.c_iflag |= ICANON; 
    tty.c_iflag &= ~OPOST; 

    if (tcsetattr(fd, TCSANOW, &tty) != 0) { 
     printf("Error from tcsetattr: %s\n", strerror(errno)); 
     return -1; 
    } 

    return 0; 
} 

void 
write_serial (int fd, const char *buf, int len) 
{ 
    printf("WRITE: %s\n", buf); 
    write(fd, buf, len); 
} 

void 
read_serial (int fd, char *buf, int len) 
{ 
    ssize_t nread = read(fd, buf, len); 
    if (nread > 0 && nread <= len) { 
     buf[nread] = 0; 
     printf(" READ: %s\n", buf); 
    } 
} 

int 
main (int argc, char **argv) 
{ 
    char buf[80]; 
    int fd = open(_TTY, O_RDWR | O_NOCTTY); 

    if (fd < 0) { 
     fprintf(stderr, "Can't open %s: %s\n", _TTY, strerror(errno)); 
     goto exit; 
    } 

    if (set_interface_attribs(fd, B115200) < 0) { 
     goto exit; 
    } 

#ifdef DEVICE 
    printf("device: %s\n", _TTY); 
    write_serial(fd, "d\n", 2); 
    usleep((2 + 25) * 100); 
    read_serial(fd, buf, 2); 
#else 
    printf("host: %s\n", _TTY); 
    read_serial(fd, buf, 2); 
    //usleep((2 + 25) * 100); 
    write_serial(fd, "h\n", 2); 
#endif 

    close(fd); 
exit: 
    return 0; 
} 
+0

'#define DEVICE'を入れて、' #ifdef DEVICE'によって制御されるコンパイルバージョンを満たすことができましたか? –

+0

'-DDEVICE'でコンパイルして起動します。 – Leroy

+0

ああ、コードにコメントされています。しかし、私はそれが好きではない - 指のトラブルにつながる可能性があります。コンパイルに失敗するとコンパイルが失敗するように、*特定の値*を定義する必要があります。 –

答えて

0

私はこのプロジェクトを進めていくうちに、皆さんの答えから多くを学び、感謝しています。しかし、の場合、という特定のケースでは、問題は許可されました。うん、ttyGSOにファイルのアクセス許可。

permission deniedのエラーはopenから完全に予想されていましたが、決してその可能性は考えられませんでした。特にRDWRモードでファイルを開いたので、私はシリアルファイルに書き込むことができました。が表示されました。私はデータを読み込んでいましたが(同じデータですが)、私は読み込み権限がありませんでした。

4

(@MarkPlotnickがコメントしたように)ECHO属性を無効にしないで横に2つの誤用割り当て、あなたがしている:ここで私が使用しているコードがある

tty.c_iflag |= ICANON; 

ICANONがLFLAGメンバーに属し、

tty.c_iflag &= ~OPOST; 

OPOSTはoflagメンバーに属します。
これらのエラーを考慮して、@ MarkPlotnickの提案を適切に適用しましたか?

作業標準設定の場合はWorking with linux serial port in C, Not able to get full dataを参照してください。

cfsetospeed(&tty, (speed_t)speed); 
cfsetispeed(&tty, (speed_t)speed); 

tty.c_cflag |= CLOCAL | CREAD; 
tty.c_cflag &= ~CSIZE; 
tty.c_cflag |= CS8;   /* 8-bit characters */ 
tty.c_cflag &= ~PARENB;  /* no parity bit */ 
tty.c_cflag &= ~CSTOPB;  /* only need 1 stop bit */ 
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */ 

tty.c_lflag |= ICANON | ISIG; /* canonical input */ 
tty.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN); 

tty.c_iflag &= ~INPCK; 
tty.c_iflag |= IGNCR; 
tty.c_iflag &= ~(INLCR | ICRNL | IUCLC | IMAXBEL); 
tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* no SW flowcontrol */ 

tty.c_oflag &= ~OPOST; 

エコー遠端で有効になっていることも可能であることに注意してください。
ローカルまたは遠端からエコーが生成されているかどうかを判断するには、リモートデバイスを切断するだけです(UARTやUSBシリアルアダプターを使用していると仮定します)。
まだエコーが得られた場合は、termios ECHO属性によって制御され、ローカルで生成されます。
エコーがもう消えない場合は、入力を送信者に戻すのはリモートユニットです。


BTW投稿されたあなたのプログラムは、きちんとコンパイルされません。
それは#include <string.h>
コピーした(が、その後誤って変更)のtermios初期化ルーチンが欠落していますが、戻り値の適切なチェックを持っていますが、あなたの読み取りおよび書き込みルーチンは、エラーをチェックしません。

関連する問題