# Mit c++ von serieller Schnittstelle lesen



## lukelukeluke (13. Mai 2011)

Hallo,
Versuche seit Stunden von ner seriellen Schnittstelle zu lesen, auf Mac OS X (also Verhalten wie Linux). Habe div Programmschnipsel auf Internet gefunden und getestet (z.B. Siehe unten). Das Problem ist immer das gleiche: Mein serielles Gerät sendet was, das kriege ich auch angezeigt, aber auch wenn ich nichts mehr sende Empfange ich immer wieder die gleichen Daten, endlos sozusagen. Liegt das an irgendwelchen Speichern die ich nicht lösche, oder kann es sein das mein Serial Adapter, resp. dessen Treiber einfach nicht zu gebrauchen ist?
Hier ist mein Code:

```
//http://www.openframeworks.cc/setup/xcode
//http://openmtproject.sourceforge.net/doc/mtview/classof_serial.html#ab0b70837b7a0ffc7f71d4ae381857c41
//http://en.wikibooks.org/wiki/Serial_Programming/termios

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>	// For FIONREAD
#include <stdlib.h>

// Standard:
#include <iostream>
// openFramework:
//#include "ofMain.h"
//#include "ofAppGlutWindow.h"
// Eigene includes:
//#include "BufferManager.h"

using namespace std;


struct termios tio;
struct termios stdio;
int tty_fd;				// Serial handle
fd_set rdset;
int res;
int bytes_avaiable;
int readamount;

char buf[1025];			// Buffer


BufferManager mybuf;

void setup_serial() {
	//printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
	
	memset(&stdio,0,sizeof(stdio));
	stdio.c_iflag=0;
	stdio.c_oflag=0;
	stdio.c_cflag=0;
	stdio.c_lflag=0;
	stdio.c_cc[VMIN]=1;
	stdio.c_cc[VTIME]=0;
	
	tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
	tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
	
	//fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);       // make the reads non-blocking (funktioniert nicht wenn auskommentiert)
	
	
	memset(&tio,0,sizeof(tio));
	tio.c_iflag=0;
	tio.c_oflag=0;
	tio.c_cflag=CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
	tio.c_lflag=0;
	
	tio.c_cc[VMIN]=1;
	tio.c_cc[VTIME]=5;
	
	tty_fd=open("/dev/tty.PL2303-0000201A", O_RDWR | O_NONBLOCK);      
	cfsetospeed(&tio,B115200);            // 115200 baud
	cfsetispeed(&tio,B115200);            // 115200 baud
	
	//tcflush(tty_fd, TCIFLUSH);
	tcsetattr(tty_fd,TCSANOW,&tio);
	 
}

int main(int argc,char** argv) {
	
	
	//unsigned char c='D';
	
	setup_serial();
	
	
	for(int i=0;i<99999999;i++) {
		
		ioctl(tty_fd, FIONREAD, &bytes_avaiable);
		
		if(bytes_avaiable>1024) { readamount=1024; }
		else { readamount=bytes_avaiable; }
		
		
		if(readamount>0) {
			
			res = read(tty_fd,buf,readamount-1);
			
			buf[readamount-1] = '\0';
			cout << buf;
		}
		
		
		//sleep (1);
	}
	
	close(tty_fd);
}
```


----------



## deepthroat (13. Mai 2011)

Hi.

Du prüfst ioctl nicht und du prüfst "res" nicht. Vermutlich wurde gar nichts gelesen und bytes_avaiable bzw. buffer blieben einfach unverändert.

Gruß


----------



## lukelukeluke (13. Mai 2011)

Ciao dt,
Danke für deine Antwort, hat mir einige Zeit gespart. Konnte es nun lösen indem ich "res" prüfe. Wie ich ioctl prüfen soll habe ich zwar nicht gesehen, ist anscheinend aber auch nicht nötig.
Hier die Änderung in meinem Code:

```
// Serial auslesen
		
		ioctl(tty_fd, FIONREAD, &bytes_avaiable); // bytes available herausfinden
		
		if(bytes_avaiable>1024) { readamount=1024; }
		else { readamount=bytes_avaiable; }
		
		if(readamount>30) {
			
			res = read(tty_fd,buf,readamount);
			
			if(res>0) {
				buf[readamount] = '\0';
				cout << buf;
				mybuf.processInput(buf);
			}
		}
```


----------



## deepthroat (14. Mai 2011)

Hi.

Die Funktion ioctl gibt -1 bei einem Fehler zurück.  "man ioctl"

Gruß


----------



## lukelukeluke (16. Mai 2011)

Ah ja hab erst jetzt gesehen dass ioctl auch eine Rückgabe hat, hab ie erst gar nicht gefunden auf cplusplus.com (?)
Leider hat sich obiges Problem aber immer noch nicht gelöst, resp. es hat nur funktioniert weil ich einen Neustart gemacht habe...


----------



## deepthroat (16. Mai 2011)

lukelukeluke hat gesagt.:


> Ah ja hab erst jetzt gesehen dass ioctl auch eine Rückgabe hat, hab ie erst gar nicht gefunden auf cplusplus.com (?)
> Leider hat sich obiges Problem aber immer noch nicht gelöst, resp. es hat nur funktioniert weil ich einen Neustart gemacht habe...


Zeig deinen aktuellen Code.

Gruß


----------



## lukelukeluke (16. Mai 2011)

Habe folgendes in der main(), nach 20 Sekunden wird abgebrochen:

```
SerialConnection myserial;

myserial.setupSerial();

for(int i=0;;i++) {
	if(counter == 20) { break; }
	// Sleep for 1 milliseconds
	
	struct timespec timeOut,remains;
	timeOut.tv_sec = 0;
	timeOut.tv_nsec = 1000000;
	nanosleep(&timeOut,&remains);
	
	if(i==1000) {
		// Output data for debug
		//
		i=0;
		counter++;
	}
	
	// Grab serial data
	cout << myserial.returnSerialDataIfAvailable(false);
}

myserial.closeSerial();
```
 
und dann das File SerialConnection.cpp das ich include:

```
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>	// For FIONREAD
#include <stdlib.h>
#include <iostream>

#include "SerialConnection.h"

using namespace std;


SerialConnection::SerialConnection() {
	serialadapter = "/dev/tty.PL2303-0000201A";
}

void SerialConnection::setupSerial() {
	//printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
	
	memset(&stdio,0,sizeof(stdio));
	stdio.c_iflag=0;
	stdio.c_oflag=0;
	stdio.c_cflag=0;
	stdio.c_lflag=0;
	stdio.c_cc[VMIN]=1;
	stdio.c_cc[VTIME]=0;
	
	tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
	tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
	
	tcsetattr(tty_fd, TCSAFLUSH, &stdio);
	
	//fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);       // make the reads non-blocking (funktioniert nicht)
	
	memset(&tio,0,sizeof(tio));
	tio.c_iflag=0;
	tio.c_oflag=0;
	tio.c_cflag=CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
	tio.c_lflag=0;
	
	tio.c_cc[VMIN]=1;
	tio.c_cc[VTIME]=5;
	
	tty_fd=open("/dev/tty.PL2303-0000201A", O_RDWR | O_NONBLOCK);      
	cfsetospeed(&tio,B115200);            // 115200 baud
	cfsetispeed(&tio,B115200);            // 115200 baud
	
	//tcflush(tty_fd, TCIFLUSH);
	tcsetattr(tty_fd,TCSANOW,&tio);
	
	// Sleep necessary to avoid errors
	sleep(1);
}

// Function that returns string with data if there is available
string SerialConnection::returnSerialDataIfAvailable(bool debug) {
	string serialdata = "";
	char *buf;
	ioctl(tty_fd, FIONREAD, &bytes_avaiable); // bytes available herausfinden
	if(bytes_avaiable>1024) { readamount=1024; }
	else { readamount=bytes_avaiable; }
	if(readamount>20) {
		buf = (char*) malloc (readamount+1);
		res = read(tty_fd,buf,readamount);
		if(res>0) {
			buf[readamount] = '\0';
			serialdata += buf;
		}
		free (buf);
	}
	if(debug && serialdata != "") { /* cout << "Received: " << serialdata << "\n"; */ }
	return serialdata;
}

void SerialConnection::closeSerial() {
	close(tty_fd);
}

// Function for Debugging: Works to read Data from serial and output it on console
void SerialConnection::readSerialDataDebug(SerialConnection myserial) {
	char buf[1050];
	ioctl(tty_fd, FIONREAD, &bytes_avaiable); // bytes available herausfinden
	if(bytes_avaiable>1024) { readamount=1024; }
	else { readamount=bytes_avaiable; }
	if(readamount>30) {
		res = read(tty_fd,buf,readamount);
		if(res>0) {
			buf[readamount] = '\0';
			cout << buf << "\n";
		}
	}
}
```

und noch SerialConnection.h:

```
#include <termios.h>
using namespace std;
class SerialConnection {
	struct termios tio;
	struct termios stdio;
	int tty_fd;				// Serial handle
	fd_set rdset;
	int res;
	int bytes_avaiable;
	int readamount;	
	//char buf[1050];			// Buffer	
	string serialadapter;	
public:	
	SerialConnection();	
	void setupSerial();	
	string returnSerialDataIfAvailable(bool debug=false);	
	void closeSerial();	
	void readSerialDataDebug(SerialConnection myserial);	
};
```


----------



## deepthroat (17. Mai 2011)

Hi.

Du prüfst immer noch nicht den Rückgabewert von ioctl.

Und statt

```
buf[readamount] = '\0';
serialdata += buf;
```
besser so:

```
data.append(buf, readamount);
```
Gruß


----------

