Ich muss demnächst ein Gerät über die serielle Schnittstelle ansteuern. Dazuhab ich hier im Board schon diverse Threads gefunden und sogar ein Beispielprogramm, das ich ganz gut benutzen konnte. Ich hab das Beispiel jetzt aufgedröselt und in eine Qt-App verpackt. Leider ergibt sich das Problem, das ein Segfault auftaucht, den ich nicht nachvollziehen kann und GDB meldet auch nur, das er auf den Speicher an der Stelle 0xirgendwas nicht zugreifen kann. Der Segfault soll in der Methode QObject::recievers(const char*) auftritt, und zwar immer dann, wenn ich die Methode closePort aufrufe. Ich nehme stark an, das es nicht an tim->stop() liegt, weil ich das vorher nicht drinn hatte und der Fehler trotzdem auftrat. Erschwerend kommt hinzu, das ich den Quelltext zwar nachvollziehen kann, aber zum Teil nicht verstehe, warum der Originalautor das so und nicht anders gemacht hat. Entsprechende Stellen habe ich gekennzeichnet. Vielleicht kann sich jmd. einene Reim drauf machen, warum das so gemacht wurde. Ich verstehe z.B. nicht, warum lowlevel-DateiIO verwendet wurde. Mit Highlevel-DateiIO könnte ich aus dem FILE* ein QFile machen und wär fein aus dem Schneider. Ich bedanke mich schonmal im Vorraus für jegliche Mühen, weil ich finde, es ist schon recht viel von mir verlangt. Zum Testen verwende ich im Moment ein HandGPS, das nur Ascii-Daten rausgibt und als Flowcontroll Software nimmt (Kabel hat nur drei Adern). Wie man an den verschiedensprachigen Kommentaren sieht, hat der Autor woll auch ganz gut mit der Zwischenablage gearbeitet.
Code:
#include <qvbox.h>
#include <qapplication.h>
#include <qtextedit.h>
#include <qtimer.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <qpushbutton.h>
class TerminalWidget : public QVBox
{
Q_OBJECT
public:
TerminalWidget(QWidget* parent = 0);
~TerminalWidget();
public slots:
void readComData();
void openPort();
void closePort();
private:
QTextEdit* out;
int fd;
QTimer* tim;
QPushButton* btnOpen, *btnClose;
QString outbuffer;
};
TerminalWidget::TerminalWidget(QWidget* parent) : QVBox(parent), fd(0)
{
out = new QTextEdit(this);
out->setTextFormat(LogText);
btnOpen = new QPushButton("Open Port", this);
btnClose = new QPushButton("Close Port", this);
connect(btnOpen, SIGNAL(clicked()), this, SLOT(openPort()));
connect(btnClose, SIGNAL(clicked()), this, SLOT(closePort()));
tim = new QTimer(this);
connect(tim, SIGNAL(timeout()), this, SLOT(readComData()));
}
TerminalWidget::~TerminalWidget()
{
closePort();
}
void TerminalWidget::openPort()
{
closePort() ;
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0)
{
printf("FEHLER : Kann Port nicht Oeffnen : %d %s\n", errno, strerror(errno));
}
else
{
struct termios my_termios;
tcgetattr(fd, &my_termios);
tcflush(fd, TCIFLUSH);
/* Baudrate und BIT-Flags werden hier gesetzt */
my_termios.c_cflag = B4800 | CS8 |CREAD | CLOCAL | HUPCL | IXON | IXOFF;
cfsetospeed(&my_termios, B4800);
tcsetattr(fd, TCSANOW, &my_termios);
}
tim->start(10);
}
void TerminalWidget::closePort()
{
if (fd > 0)
{
tim->stop();
close(fd); // <-- Das ist wohl was ganz böses
}
}
void TerminalWidget::readComData()
{
int iIn;
char buffer[4096];
int iMax = 4096;
if (fd < 1)
{
printf("FEHLER : Kein Port offen \n");
return;
}
strncpy (buffer, "N/A", iMax < 4 ? iMax : 4); // <-- Wozu?
/* Hier werden die Daten vom Port eingelesen */
iIn = read(fd, buffer, 4095);
if (iIn < 0)
{
if (errno == EAGAIN)
return; // assume that command generated no response
else
printf("FEHLER : Lesefehler %d %s\n", errno, strerror(errno));
}
else
{
buffer[iIn<iMax?iIn:iMax] = '\0';
}
outbuffer.append(buffer);
out->setText(outbuffer);
}
#include "serial.moc.cpp"
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
TerminalWidget tw;
app.setMainWidget(&tw);
tw.show();
return app.exec();
}
Lesezeichen