[Solved]QtSerialPort receiver gets stuck
-
Hi - I'm a newbie, so apologies if I get things wrong!
I am using QtSerialPort in a small project (in Windows) to test communications with a TI Stellaris microcontroller. They are connected via a USB virtual serial port.
It nearly works perfectly except that sometimes the readyRead() signal stop being emitted.
The problem occurs when I implement an "echo" function ie. I send the data packet back out of the serial port immediately on receiving it. (The idea being that I can check in the micro that I get back exactly what I sent).
The echo function works fine for a few packets but then stops. I can see the serial data from the micro going into the serial port on a scope but the readyRead() signal is not emitted.
I am aware that QtSerialPort may be running in it's own thread and I have tried using Qt::QueuedConnection thus...
@connect(serial, SIGNAL(readyRead()), this, SLOT(readData()), Qt::QueuedConnection);@But this doesn't make any difference (I think this is default between threads anyway).
Doing the echo the other way round works fine (ie sending a packet from Qt to the micro and the micro sending it back immediately).
The packets I'm sending are just a few bytes long.
I have studied the examples supplied when I downloaded QtSerialPort (terminal), but being new to this I can't see any mutexes or threading issues there. I suppose the problem could be with the Windows driver so another task would be to connect direct to a physical serial port.
Any ideas or hints etc would be most welcome.
Thank you very much - I'm enjoying Qt so far :)
-
Does it stop the first time you send or after some fixed number of sends/bytes, or some indeterminate time? Buffering filling up perhaps.
How are you sending? Just calling write() or are you calling waitForBytesWritten() or some other blocking code.
Try distilling the code to the minimum needed to reproduce the behaviour and post it.
-
Thanks for your advice.
Here is a simple program "SerialTest" which demonstrates my problem...
@#include "mainwindow.h"
#include "ui_mainwindow.h"#include <QtSerialPort/QSerialPort>
#include <QDebug>//----------------------------------------------------------------------------------
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);serial = new QSerialPort(this); connect(serial, SIGNAL(readyRead()), this, SLOT(readData()), Qt::QueuedConnection); serial->setPortName("COM4"); if (serial->open(QIODevice::ReadWrite)) { if (serial->setBaudRate(QSerialPort::Baud115200) && serial->setDataBits(QSerialPort::Data8) && serial->setParity(QSerialPort::NoParity) && serial->setStopBits(QSerialPort::OneStop) && serial->setFlowControl(QSerialPort::NoFlowControl)) { } else { serial->close(); } } else { serial->close(); }
}
//----------------------------------------------------------------------------------
MainWindow::~MainWindow()
{
delete ui;
}//----------------------------------------------------------------------------------
void MainWindow::on_pushButton_clicked()
{
int nWritten;
QByteArray data;
static int number = 0;data[0] = 0xF0; //0xF0 makes a single pulse - easy to trigger scope nWritten = serial->write(data, 1); if(nWritten == -1) qDebug() << "error sending button data"; else { number ++; qDebug() << nWritten << "bytes sent from button" << number; }
}
//----------------------------------------------------------------------------------
void MainWindow::readData()
{
static int numb = 0;if(serial->bytesAvailable() == 0 ) { qDebug() << "nothing to Rx : bad signal?"; //just checking return; } QByteArray data = serial->readAll(); //throw away data, maybe not necessary? numb ++; qDebug() << data.size() << "bytes received" << numb; data.clear();
//......................................................................
int nWritten; //send a byte as ack response
static int number = 0;data[0] = 0xF0; nWritten = serial->write(data, 1); serial->waitForBytesWritten(100); //without this the rx fails after the first byte //with it the exchange can last seconds if(nWritten == -1) qDebug() << "error sending ack"; else { number ++; qDebug() << nWritten << "bytes sent as ack" << number; }
}
@
As you see the UIs MainWindow starts up the serial port and has a single button.
The serial port hardware is connected to my microcontroller whose response to any data received is to send back an 0xF0 "acknowledge" byte. The SerialTest code above also has this response.
Pressing the button on the UI sends an 0xF0 which starts a constant exchange of bytes.This exchange stops after a few exchanges (see comments) and the problem is that the readyRead() signal is not emitted when the serial port is sent a byte (I can see it on the scope). Also the UI button continues to output correctly.
Can you see what I've done wrong? I can't find much documentation which is why I guessed at using the "wait for" function - is there a link to the latest docs do you know?
Thank you for your time.
-
I should have said that the micro is scanning for received bytes every 1.5mS which limits the throughput. On the scope the gap between exchanges was between 1.5mS and 15mS approx. So we can be sure the processor has plenty of time I think.
best regards
-
Hi, what OS is used?
Oops, sorry, clear
-
Strange, but everything works for me.
I used the test with cross-cable use between two ports on one PC. On the one hand it is connected to built-in port which imitates the microcontroller. On the other hand to USB/Serial the converter (on the PL2303 chip) which imitates the program.
-
The microcontroller simulator: simply transfers to the port with some periodicity data packets.
-
The simulator of the program accepts request, reads it (with an output in the console) and sends to the response one byte 0xF0.
For testing stream I use my simple test application "CpuUsageTester":http://www.filehostfree.com/?d=516D8E2F1
To configure need select options as on "picture ":http://s24.postimg.org/6w53ddwxx/config.png
-
-
I would remove the queued connection and waitFroBytesWritten() both of which are unnecessary.
Have you tried it at lower speed?
-
Thank you very much for your support with this.
I managed to test this on a native Linux machine - never ceases to amaze me that my sources just work on a different OS :) The serial port worked fine!
Next I went back to my Windows machine, built an rs232/TTL convertor and tested it with a real hardware serial port - worked fine too!
So the problem lies with the USB virtual serial port driver on my Windows PC.
Very sorry to have troubled you and many thanks for your support.
Is it right I should rename this thread with Solved?
-
What USB/Serial type (on what chip) the converter you used?
At least what VID/PID at it? -
The microcontroller I'm using is the Texas LM4F120 on their "LaunchPad" prototyping board. It has an on-board In Circuit Debug interface and a usb serial port wired to the micros uart. The Windows driver for this is supplied by Texas and the version I have is the latest they have published I believe. I will contact them about this in due course.
-
Ok, thx. Clear.