An annoying problem about QSerialPort usage
-
[quote author="kuzulis" date="1378888607"]Hi guys. I'm here. :)
Ivan,
- What OS is used?
- What serial chip/model is used?
- Please give the minimum console example which reproduces this problem.
- Still I don't recommend to use waitForXX() methods. Use non-blocking approach instead of the blocking.
- Mr. Koahning mean use just read() method instead of readAll(). Try and let know about results. [/quote]
Thanks a lot for picking up the discussion.
Using SerialPort in the title line seems to work very quick ;-)
Sorry, that I could not remember your name. -
Ivan, Can you e-mail for me your project?
-
Sure, but i need your e-mail address.
-
Hi, I simplify my code like following, please check:
pro file
@
QT += core serialportQT -= gui
TARGET = QSerialPortDebug
CONFIG += console
CONFIG -= app_bundleTEMPLATE = app
SOURCES += main.cpp
worker.cppHEADERS +=
worker.h@
worker.h
@
#ifndef WORKER_H
#define WORKER_H#include <QObject>
#include <QFile>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>class worker : public QObject
{
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
QFile file;
QSerialPort *serialPort;
QList<QSerialPortInfo> SerialInfo;
QByteArray readData;
QByteArray ReceiveData;
QString sendData;
void InitialComport();signals:
public slots:
};
#endif // WORKER_H
@worker.cpp
@
#include "worker.h"worker::worker(QObject *parent) :
QObject(parent)
{
serialPort = new QSerialPort();
InitialComport();
file.setFileName("Image.hex");
}
void worker::InitialComport()
{
SerialInfo = QSerialPortInfo::availablePorts();
serialPort->setPort(SerialInfo[0]);
serialPort->open(QSerialPort::ReadWrite);
serialPort->setBaudRate(QSerialPort::Baud38400);
serialPort->setDataBits(QSerialPort::Data8);
serialPort->setStopBits(QSerialPort::OneStop);
serialPort->setParity(QSerialPort::NoParity);
}@
main.cpp
@
#include <QCoreApplication>
#include <QThread>
#include <worker.h>
#include <QTextStream>
#include <QDebug>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
worker WORKER;
WORKER.file.open(QIODevice::ReadWrite);
QTextStream Image(&WORKER.file);
while (Image.atEnd()) {
WORKER.sendData = Image.readLine();
WORKER.serialPort->write(WORKER.sendData.toLocal8Bit());
for(int i = 0; i <30; i++)
{
while(WORKER.serialPort->waitForReadyRead(35))
{
WORKER.ReceiveData = WORKER.serialPort->read(50);
}
if(WORKER.ReceiveData.length() != 0)
break;
}
qDebug() << QString(WORKER.ReceiveData);
WORKER.ReceiveData.clear();
}
WORKER.serialPort->close();
return a.exec();
}@
-
I'm sorry, but your example is incorrect.
I used the yourself a loopback example with use "Com0Com":http://sourceforge.net/projects/com0com/
Emulation of baud rate in Com0Com has to be enabled.
I used two Flasher and Eeprom applications to your I/O emulation.
Flasher:
(main.cpp)
[code]
#include <QCoreApplication>
#include <QFile>
#include <QElapsedTimer>
#include <QDebug>
#include <qserialport.h>int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);QSerialPort serialPort; serialPort.setPortName("COM4"); bool ret = serialPort.open(QSerialPort::ReadWrite) && serialPort.setBaudRate(QSerialPort::Baud38400) && serialPort.setDataBits(QSerialPort::Data8) && serialPort.setStopBits(QSerialPort::OneStop) && serialPort.setParity(QSerialPort::NoParity); qDebug() << "serial port: " << ret; QFile sourceHexImage("path/to/source/image/src.hex"); ret = sourceHexImage.open(QIODevice::ReadOnly); qDebug() << "source image ret: " << ret; QFile destinationHexImage("path/to/destination/image/dst.hex"); ret = destinationHexImage.open(QIODevice::WriteOnly | QIODevice::Truncate); qDebug() << "destination image ret: " << ret; QElapsedTimer timer; timer.start(); const int ioChunkSize = 25; // bytes const int waitTimeout = 35; // msec while (!sourceHexImage.atEnd()) { QByteArray chunk = sourceHexImage.read(ioChunkSize); serialPort.write(chunk); ret = serialPort.flush(); while (serialPort.waitForReadyRead(waitTimeout)) { if (serialPort.bytesAvailable() == ioChunkSize) break; } chunk = serialPort.read(ioChunkSize); destinationHexImage.write(chunk); } serialPort.close(); sourceHexImage.close(); destinationHexImage.close(); qDebug() << timer.elapsed() << "msec, done..."; return a.exec();
}
[/code]Eeprom emulator - Echo application
(main.cpp)
[code]
#include <QCoreApplication>#include "echo.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Echo echo;
echo.init();
return a.exec();
}
[/code](echo.h)
[code]
#ifndef ECHO_H
#define ECHO_H#include <QDebug>
#include <qserialport.h>class Echo : public QObject
{
Q_OBJECT
public:
explicit Echo(QObject *parent = 0 ) : QObject(parent) {
connect(&serialPort, SIGNAL(readyRead()), this, SLOT(onEcho()));
}bool init() { serialPort.setPortName("COM5"); bool ret = serialPort.open(QSerialPort::ReadWrite) && serialPort.setBaudRate(QSerialPort::Baud38400) && serialPort.setDataBits(QSerialPort::Data8) && serialPort.setStopBits(QSerialPort::OneStop) && serialPort.setParity(QSerialPort::NoParity); return ret; }
private slots:
void onEcho() {
const QByteArray data = serialPort.readAll();
qDebug() << data;
serialPort.write(data);
}private:
QSerialPort serialPort;
};#endif // ECHO_H
[/code]I have no SEGFAULT.
-
Thanks for your test.But actually when I receive packet from Comport, I need to collect complete packet that my program then could parse correctly, so I can't give the constant number that used on serialport->read().My original program for serialPort is run on another thread I created, because I want to show information on GUI. Does it make my program fail......, why sometimes my program could work, sometimes would crashed....., they run on same code.....
-
bq. But actually when I receive packet from Comport, I need to collect complete packet that my program then could parse correctly, so I can’t give the constant number that used on serialport->read().
I'm too collect data up to 25 bytes. (ioChunkSize = 25).. And in principle, it makes no difference...
bq. My original program for serialPort is run on another thread I created, because I want to show information on GUI.
To avoid of potential errors - just use an non-blocking approach, it will be simple and more safely.
-
"non-blocking method" is you mentioned on "Eeprom emulator – Echo application" ??
bq. I’m too collect data up to 25 bytes. (ioChunkSize = 25).. And in principle, it makes no difference…
I mean I don't know how many bytes I should receive until I don't receive any data from serialPort.
-
bq. “non-blocking method” is you mentioned on “Eeprom emulator – Echo application” ??
Yes.
bq. I mean I don’t know how many bytes I should receive until I don’t receive any data from serialPort.
I know that you mean. In an example which I gave, 25 bytes it is simple an example. My example is used for trying to detect of crash in case of the intensive I/O.
-
I still think there is a problem inside, could you try using QtserialPort with a Qthread??
-
bq. could you try using QtserialPort with a Qthread??
You can use as well QThread.
But I have no free time on detection of your crash and I can't reproduce your crash.
Please give for me an simple projects with emulation of Flasher & Eeprom with use Com0Com which reproduce a problem. Because in other case, I can't help to you because I do not have an your Hardware.
Or, you should do it yourself. For testing and debugging you have to download source codes of QtSerialPort and include them to the project directly through the *.pri file.
E.g., ourproject.pro :
[code]
QT += core
QT -= gui
TARGET = ourproject
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = appinclude(path/to/serialport-lib.pri)
SOURCES += oursources.cpp
HEADERS += ourheaders.h
[/code]Of course, it is necessary to fix some errors when compilation, by some modification of the QtSerialPort files. It will allow you to receive a call-stack and to detect a cause of crash.
-
Thank you very much : ).