QextSerialPort

Alles rund um die Programmierung mit Qt
archon
Beiträge: 117
Registriert: 22. August 2006 12:01

Beitrag von archon »

So, da ich bis jetzt keine andere Möglicheit gefunden hab verwende ich zunächst mal eine Polling abfrage um die serielle Schnittstelle abzufragen.

Folgender Code öffnet einen Thread der dann alle 500ms auf den Buffer schaut ob dieser was hat oder nicht hat. Wenn was kommt gibt er dies auf einem textedit im Mainwindow aus.

mainform.h:

Code: Alles auswählen

#ifndef MAINFORM_H
#define MAINFORM_H

#include <QtGui/QMainWindow>
#include <QIODevice>
#include <QTimer>
#include "ui_mainform.h"
#include "serialthread.h"

class QextSerialPort;
class QextSerialBase;

class mainform : public QMainWindow, private Ui::MainForm
{
    Q_OBJECT

public:
	QextSerialPort *port;
	serialThread sThread;	

    mainform(QWidget *parent = 0);
    ~mainform();

private:
    Ui::MainForm ui;
    
private slots:
	void send_cmd();
	void receiveMsg(char *);
	void toLog();
    
};

#endif // MAINFORM_H
mainform.cpp:

Code: Alles auswählen

#include "mainform.h"
#include <qextserialport.h>
#include <QIODevice>

#include <serialthread.h>

mainform::mainform(QWidget *parent)
    : QMainWindow(parent), port(NULL)
{
	setupUi(this);
    
	connect(sendPushButton, SIGNAL(clicked()), this, SLOT(send_cmd()));
	connect(&sThread, SIGNAL(signalSerialData(char *)), this, SLOT (receiveMsg(char *)));

}

mainform::~mainform()
{

}

void mainform::send_cmd()
{	
	sThread.start(QThread::NormalPriority);
}

void mainform::toLog()
{
	incomingTextEdit->insertPlainText("<rec>");
}

void mainform::receiveMsg(char *t)
{
	incomingTextEdit->insertPlainText(t);
}
serialthread.h:

Code: Alles auswählen

#ifndef SERIALTHREAD_H_
#define SERIALTHREAD_H_

#include <QThread>
#include <qextserialport.h>
#include <qapplication.h>


class serialThread : public QThread
{
    Q_OBJECT
	
	public:
		QextSerialPort *port;
		QTimer *pol_timer;

	    serialThread(QObject *parent = 0);	
		~serialThread();
		

	private:
		void openPort();
		void closePort();
	    void run();
		
	signals:
		void signalSerialData(char *);

private slots: 
		void checkRecBuf();	

};

#endif /*SERIALTHREAD_H_*/

serialthread.cpp:

Code: Alles auswählen


#include <serialthread.h>
#include <qextserialport.h>
#include <QTimer>
#include <QTime>


serialThread::serialThread(QObject *parent)
    : QThread(parent){}

serialThread::~serialThread(){}

/******************************************************************/

void serialThread::run()
{
	port = new QextSerialPort("COM1");
    port->setBaudRate(BAUD9600);   
    port->setFlowControl(FLOW_OFF);
    port->setParity(PAR_NONE);
    port->setDataBits(DATA_8);
    port->setStopBits(STOP_1);
	
	
    pol_timer = new QTimer(this);
	
	connect(pol_timer, SIGNAL(timeout()), this, SLOT(checkRecBuf()));
	pol_timer->start(500);
	
	openPort(); 	
	
	QString test = QString("log versiona ontime 1 \x0D\x0A");
	//QString test = QString("log rxcommandsa once \x0D\x0A");
	port->write(test.toAscii(),test.length());

	exec();
	
	
}

void serialThread::checkRecBuf()
{ 
	
	
//	emit signalSerialData("<in_checkRecBuf>");
	
	char buff[4096];
  	int numBytes=0;
  
	numBytes = port->bytesAvailable();

	if(numBytes>0) 
	{
	    QString msg = buff;
	    if(numBytes > 4096) numBytes = 4096;
	
	    int i = port->read(buff, numBytes);
		buff[i] = '\0';
		emit signalSerialData(buff);

	}
}

/******************************************************************/

void serialThread::openPort()
{
	port->open(QIODevice::ReadWrite);
	qDebug("is open: %d", port->isOpen());
}

void serialThread::closePort()
{
	port->close();
	qDebug("is open: %d", port->isOpen());
}

Komischerweise emittiert der Timer kein timeout() wenn dieser im konstruktor definiert wird. Deswegen hab ich alles in run() reingepackt.

Wenn jemand Verbesserungsvorschläge hat...nur zu!
jkob
Beiträge: 1
Registriert: 15. März 2008 11:16

Beitrag von jkob »

Hi,

ich glaube, dass dein Programm nicht korrekt ist (falls das überhaupt noch interessant für dich ist).
Für den Fall, dass 4096 Bytes zu Verfügung stehen, schreibst du in den 4096 Bytes großen Buffer an die 4097te Stelle den String-Terminator, also mitten in den Speicher.

Dein zweites Problem ist, wenn nach 500 ms regelmäßig mehr als 4096 Bytes gelesen werden könnten, gehen dir Daten verloren, da der Puffer der seriellen Schnittstelle überläuft. Wenn du nur Daten deines GPS' ausliest, sollte das kein Problem sein, da dass weniger Daten sind. Aber korrekterweise solltest den Puffer flushen.
Allerdings könnte es so natürlich passieren, dass du so einen nicht vollständig empfangenen Datensatz abschneidest.

Gruß,
Jkob
Antworten