Lesen und Schreiben an der seriellen Schnittstelle in C unter Linux

Ich versuche zuSenden / Empfangen von Daten über einen USB-Port mit FTDIDaher muss ich die serielle Kommunikation mit C / C ++ abwickeln. Ich arbeite anLinux (Ubuntu).

Grundsätzlich bin ich mit einem Gerät verbunden, das auf eingehende Befehle wartet. Ich muss diese Befehle senden und die Antwort des Geräts lesen. Sowohl Befehle als auch Antworten sindASCII-Zeichen.

Mit GtkTerm funktioniert alles einwandfrei, aber wenn ich zur C-Programmierung wechsle, treten Probleme auf.

Hier ist mein Code:

#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);

Was passiert ist dasread() Liefert 0 (keine gelesenen Bytes) oder Block bis zum Timeout (VTIME). Ich gehe davon aus, dass dies passiert, weilwrite() schickt nichts. In diesem Fall empfängt das Gerät keinen Befehl und ich kann keine Antwort erhalten. Das Ausschalten des Geräts, während das Lesen meines Programms blockiert ist, hat tatsächlich zu einer Antwort geführt (das Gerät sendet beim Herunterfahren etwas).

Seltsam ist, dass man das hinzufügt

cout << "I've written: " << n_written << "bytes" << endl; 

gleich nachwrite() Anruf, ich erhalte:

I've written 6 bytes

Das ist genau das, was ich erwarte. Nur mein Programm funktioniert nicht so, wie es sein sollteMein Gerät kann nicht empfangen, was ich gerade schreibe im Hafen.

Ich habe verschiedene Dinge und Lösungen ausprobiert, auch in Bezug auf Datentypen (ich habe versucht, std :: string zu verwenden, wie zcmd = "INIT \r" oderconst char) aber nichts hat wirklich funktioniert.

Kann mir jemand sagen, wo ich falsch liege?

Danke im Voraus.

BEARBEITEN: Zuvor verwendete Version dieses Codes

unsigned char cmd[] = "INIT \n"

und auchcmd[] = "INIT \r\n". Ich habe es geändert, weil der Befehl sintax für mein Gerät als gemeldet wird

<command><SPACE><CR>.

Ich habe auch versucht, das zu vermeidenO_NONBLOCK flagge beim lesen, aber dann sperre ich nur bis auf ewig. Ich habe versucht mitselect() aber nichts passiert. Nur zum Ausprobieren habe ich eine Warteschleife erstellt, bis Daten verfügbar sind, aber mein Code verlässt die Schleife nie. Übrigens warten oderusleep() muss ich vermeiden. Gemeldete ist nur ein Auszug aus meinem Code.Der vollständige Code muss in einer Echtzeitumgebung funktionieren (speziell OROCOS) Ich möchte also nicht wirklich eine schlafähnliche Funktion.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage