PDA

View Full Version : Qserialdevice 2.0 waitForBytesWritten halfduplex question



egadget1
12th February 2012, 20:59
I have a question, writing a Qt GUI and I have the RTS line connected to a RS-485 driver transmit/receive control signal. I am sending out x number of bytes, I use the setRts(1) to make it go high (start of transmisson) and setRts(0) when I finish (as direction control). Does the waitForBytesWritten method work? I want it to wait until all the bytes have been transmitted out of the serial port, so I can setRts low. I see that sometimes the RTS signal is going low before all the bytes have been transferred. Any one have any ideas?

Do I have to set it up in unbuffered mode?

Here is a snippet of my code. Thanks in advance.


void TraceDialog::procSendButtonClick()
{
QByteArray data;
data.append(ui->lineEdit->text());
m_port->setRts(1);
if (data.size() > 0) {
m_port->write(data);
printTrace(data, false);
ui->lbError->setText(QString::number(m_port->error()));
}
// Add in sleep timer

while(m_port->waitForBytesWritten(15)); // Time out for 15 ms

m_port->setRts(0);
}

kuzulis
13th February 2012, 11:34
To be honest, this method waitForBytesWritten() has not been tested.

>Do I have to set it up in unbuffered mode?
Try it.

egadget1
20th February 2012, 20:01
Hi Kuzulis,

I see your the expert in qserialdevice. I added a delay (depends on bytes sent and baud rate) to change the RTS signal. Seems to work.

I have another question I want to receive back a variable string of bytes. The first byte contains the amount (max is 255) is there a way to read one byte and then read x bytes depending on the first byte? In the code below I see the first byte with a msgsize of 15, but I don't see the 15 bytes of data. I know they are coming over because I can see them on the logic analzer. Do you know what is wrong?

Thanks

void TraceDialog::procReadyRead()
{
while(m_port->bytesAvailable() < 1) {} //wait for datacount

char msgsize[1];
// Read the first byte to determine amount of bytes
qint64 datacnt = m_port->read(msgsize, 1);

char datamsg[32];
while(m_port->bytesAvailable() == 15) {} //wait for datacount
qint64 data2cnt = m_port->read(datamsg, 15);
//QByteArray data = m_port->readAlll();

//printTrace(data, true);
ui->lbError->setText(QString::number(m_port->error()));
}

kuzulis
22nd February 2012, 18:32
Do not use call waiting with a "while", because of this, you're slow/freeze Qt event loop.

Use signals and slots.

To find out about the possibility of reading the first 15 bytes, for example, can after first emitted signal readyRead(), make to run QTimer, with wait timeout limit. Thus, after each emitting readyRead() to check the number of bytes available for reading bytesAVailable(), and if it is >= 15 then reset QTimer and read the data; if <15 then do nothing (wait for the next readyRead()). If worked signal from QTimer, then the limit has expired timeout - then do something.

Ie this approach the analysis and reading the input data will be executed asynchronously, as if with a delay in phase relative to their real receive.

So it must be done!

egadget1
26th February 2012, 21:11
Thanks for your help, this works without the timer. Going to add in a timeout if I don't get the message in (baud_rate*numbytes) time to reset msgsize back to zero. I will never use while loops in a slot.

void MainWidget::procSerialDataReceive()
{
if (this->initTraceWidget() && this->serial && this->serial->isOpen()) {

if ((msgsize == 0) && (serial->bytesAvailable() >= 1))
{
QByteArray msg_size = this->serial->read(1);
msgsize = msg_size[0];
}
if ((msgsize != 0) && (this->serial->bytesAvailable() >= msgsize))
{
QByteArray data = this->serial->read(msgsize);
msgsize = 0;
this->traceWidget->printTrace(data, true);
}
}
}