Mit c++ von serieller Schnittstelle lesen

lukelukeluke

Erfahrenes Mitglied
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:
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);
}
 
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ß
 
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:
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);
			}
		}
 
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...
 
Habe folgendes in der main(), nach 20 Sekunden wird abgebrochen:
Code:
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:
Code:
#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:
Code:
#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);	
};
 
Zuletzt bearbeitet:
Hi.

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

Und statt
C++:
buf[readamount] = '\0';
serialdata += buf;
besser so:
C++:
data.append(buf, readamount);
Gruß
 
Zurück