Lesen und schreiben auf die serielle Schnittstelle in C unter Linux

Ich versuche, senden/empfangen von Daten über eine USB-Schnittstelle mittels FTDI, also ich muss um die serielle Kommunikation mit C/C++. Ich arbeite Linux (Ubuntu).

Grundsätzlich bin ich mit einem Gerät verbunden, das ist das lauschen auf eingehende Befehle. Ich brauche zu senden, die Befehle und Gerät Lesen die Antwort. Beide Befehle und Antwort-sind ASCII-Zeichen.

Alles funktioniert gut mit GtkTerm aber, wenn ich Wechsel zu C Programmierung habe ich Probleme.

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, dass read() gibt 0 zurück (keine bytes gelesen) oder zu blockieren, bis timeout (VTIME). Ich gehe davon aus, dass dies geschieht, weil write() sendet nicht nichts. In diesem Fall Gerät würde nicht erhalten Befehl, und ich kann nicht erhalten, Reaktion. In der Tat, ausschalten des Geräts, während mein Programm blockiert, auf das Lesen eigentlich hat immer eine Antwort (Gerät sendet etwas beim Herunterfahren).

Merkwürdige ist, dass das hinzufügen dieser

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

direkt nach write() Aufruf, erhalte ich:

I've written 6 bytes

das ist genau das, was ich erwarte. Nur mein Programm funktioniert nicht wie es sollte, wie mein Gerät nicht empfangen kann, was ich eigentlich schreiben auf port.

Habe ich verschiedene Sachen ausprobiert und Lösung, auch in Bezug auf Daten-Typen (ich habe versucht, mit std::string, wie cmd = "INIT \r" oder const char), aber nichts hat wirklich funktioniert.

Kann mir jemand sagen, wo ich falsch bin?

Vielen Dank im Voraus.

EDIT:
Zuvor version von diesem code verwendet

unsigned char cmd[] = "INIT \n"

und auch cmd[] = "INIT \r\n". Ich geändert es weil Befehl Syntax für mein Gerät ist gemeldet

<command><SPACE><CR>.

Ich habe auch versucht zu vermeiden die O_NONBLOCK Flagge auf dem Lesen, aber dann habe ich nur zu blockieren, bis für immer. Ich habe versucht, mit select() aber es passiert nichts. Nur für einen Versuch, ich ' ve erstellt eine Warteschleife bis Daten verfügbar, aber mein code nie beendet die Schleife. Btw, warten oder usleep() ist etwas, was ich vermeiden müssen. Gemeldet ist, ist nur ein Ausschnitt aus meinem code. Komplette code muss in einer Echtzeit-Umgebung (speziell OROCOS) also ich möchte wirklich nicht schlafen-like-Funktion.

  • std::cout ist C++. Allgemein gesprochen, Ihre MCVE halten sollten, um eine Sprache, es sei denn, Sie vermuten eine schlechte Interaktion. Ansonsten einige Leute beginnen zu streiten C++ ist nicht C.
InformationsquelleAutor Lunatic999 | 2013-08-07
Schreibe einen Kommentar