Serial.write crashes program in Qt (C++) - c++

I am attempting to write a command to a serial port that will change my TV input, but when I try to write the necessary command to the port, I get a very strange output.
#include <QCoreApplication>
#include <QSerialPort>
#include <Windows.h>
int set_id = 0;
int fd = -1;
int main(int argc, char *argv[])
{
QCoreApplication app{argc, argv};
int timeInSeconds=0;
while(timeInSeconds>0)
{
printf("%d...\n",timeInSeconds);
Sleep(1000);
timeInSeconds--;
}
QSerialPort serial;
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
serial.setPortName("com3");
serial.open(QIODevice::ReadWrite);
/*char cmd1='x';
char cmd2='b';
int value=20;
char cmd[20];
int len;
if (value >= 0x100)
len = sprintf(cmd, "%c%c %02x %02x %02x\r", cmd1, cmd2, set_id, value>>8, value&255);
else
{
len = sprintf(cmd, "%c%c %02x %02x\r", cmd1, cmd2, set_id, value);
}
serial.write(cmd, len);
*/
char cmdHex[5]="0xc5";
serial.write(cmdHex);
serial.close();
int stall;
scanf("%d",&stall);
//return a.exec();
}
The code is supposed to change the tv input to av. (Starting from HDMI 1) Also, the block that is commented out is my first attempt at sending the command.

You should study the QSerialPort examples shipped with Qt.
There's the terminal project, which is interactive (nice for testing ports), and the cwritersync does what you're trying to do.
Here is the full cwritersync code:
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp#kde.org>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtSerialPort/QSerialPort>
#include <QTextStream>
#include <QCoreApplication>
#include <QFile>
#include <QStringList>
QT_USE_NAMESPACE
int main(int argc, char *argv[])
{
QCoreApplication coreApplication(argc, argv);
int argumentCount = QCoreApplication::arguments().size();
QStringList argumentList = QCoreApplication::arguments();
QTextStream standardOutput(stdout);
if (argumentCount == 1) {
standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]").arg(argumentList.first()) << endl;
return 1;
}
QSerialPort serialPort;
QString serialPortName = argumentList.at(1);
serialPort.setPortName(serialPortName);
int serialPortBaudRate = (argumentCount > 2) ? argumentList.at(2).toInt() : QSerialPort::Baud9600;
serialPort.setBaudRate(serialPortBaudRate);
if (!serialPort.open(QIODevice::WriteOnly)) {
standardOutput << QObject::tr("Failed to open port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
QFile dataFile;
if (!dataFile.open(stdin, QIODevice::ReadOnly)) {
standardOutput << QObject::tr("Failed to open stdin for reading") << endl;
return 1;
}
QByteArray writeData(dataFile.readAll());
dataFile.close();
if (writeData.isEmpty()) {
standardOutput << QObject::tr("Either no data was currently available on the standard input for reading, or an error occurred for port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
qint64 bytesWritten = serialPort.write(writeData);
if (bytesWritten == -1) {
standardOutput << QObject::tr("Failed to write the data to port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
} else if (bytesWritten != writeData.size()) {
standardOutput << QObject::tr("Failed to write all the data to port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
} else if (!serialPort.waitForBytesWritten(5000)) {
standardOutput << QObject::tr("Operation timed out or an error occurred for port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
standardOutput << QObject::tr("Data successfully sent to port %1").arg(serialPortName) << endl;
return 0;
}

Related

Communication between Raspberry pi (QT C++) and Arduino (Arduino IDE)

I've been trying for more than a week to communicate from raspberry pi (QT C++) to Arduino (Arduino IDE c++) through a serial port but i keep failing.
I did some searching on google, read the example... and still i didn't succeeded. Ok so the basic thing is that i need to communicate continuously the serial port sent command from Raspberry pi to Arduino. I tried to keep the code as simple as possible.
Initially I'm sending "J" char from raspberry pi (QT C++) to Arduino (Arduino IDE c++) and waiting on that J, to make the LED blink on Arduino. But it doesn't work.. Even I didn't get any sample for interfacing & communicating & sending data raspberry pi (QT C++) to Arduino (Arduino IDE c++). I don't know what is the problem exactly. Kindly help me to solve the issue.
In monitor, 9600 baudrate
I have attached program what I have tried on both side.
main.cpp
#include <iostream>
#include <QIODevice>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QString>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
QSerialPort serialPort;
serialPort.setBaudRate(QSerialPort::Baud9600);
QSerialPortInfo info("ttyUSB0");
qDebug() << "Name : " << info.portName();
qDebug() << "Description : " << info.description();
qDebug() << "Busy:" << info.isBusy();
QSerialPort serial;
serial.setPortName("ttyUSB0");
serial.open(QIODevice::ReadWrite);
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
serial.open(QSerialPort::ReadWrite);
cout<<"Readable :"<<serial.isReadable()<<endl;
cout<<"Writable :"<<serial.isWritable()<<endl<<endl;
if (serial.isOpen() && serial.isWritable())
{
qDebug() << "Is open : " << serial.isOpen() << endl;
qDebug() << "Is writable : " << serial.isWritable() << endl;
qDebug() << "Ready..." << endl;
serial.write("J");
QByteArray ba("J\n");
serial.write(ba);
{
QByteArray ba("J");
serial.write(ba);
serial.flush();
qDebug() << "data has been send" << endl;
serial.close();
}
if (serial.bytesToWrite() > 0)
{
serial.flush();
if(serial.waitForBytesWritten(1000))
{
qDebug() << "data has been send" << endl;
}
}
if(serial.flush())
{
qDebug() << "ok" << endl;
}
qDebug() <<"value sent "<< endl;
serial.close();
}
else
{
qDebug() << "An error occured" << endl;
}
return a.exec();
}
Arduino code:
int led = 13, avlb = 0;
void setup()
{
Serial.begin(9600);
pinMode(led, OUTPUT);
Serial.println("started");
}
void loop()
{
if (Serial.available() > 0)
{
Serial.println("available");
Serial.println(Serial.available());
delay(2000);
digitalWrite(led, HIGH);
delay(5000);
if(Serial.read() == 'J')
{
Serial.println("read");
Serial.println(Serial.read());
delay(2000);
digitalWrite(led, LOW);
delay(1000);
}
}
else
{
Serial.println("not available");
delay(1000);
}
}
Output Displayed:
Raspberry qt creator ide o/p:
Name : "ttyUSB0"
Description : "FT232R USB UART"
Busy: false
Readable :1
Writable :1
Is open : true
Is writable : true
Ready...
data has been send
bool QSerialPort::flush(): device not open
value sent
Arduino Ide Output displayed:
started
not available
not available
not available
not available
not available
not available
not available
not available
not available
I would suggest you to read about how Qt event system works. All Qt IODevice derived classes work asynchronously. You need to use QApplication in order to host its object system. After that, you need to change your code so that it's not blocking io thread of QSerialPort.
I usually use readyRead singal or I use waitForBytesWritten and waitForReadReady combination.You should take a look at the QtSerialPort examples. You'll find there several possible implementations depending on your application needs.
You can try this, it will work fine.
#include <QCoreApplication>
#include <iostream>
#include <QSerialPort>
#include <QDebug>
#include <Windows.h>
#include <QElapsedTimer>
using namespace std;
QSerialPort serial;
QElapsedTimer timer;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
serial.setPortName("ttyUSB0");
serial.open(QIODevice::ReadWrite);
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
while(!serial.isOpen()) serial.open(QIODevice::ReadWrite);
if (serial.isOpen() && serial.isWritable())
{
qDebug() << "Serial is open";
QByteArray output;
QByteArray input;
while(true)
{
output = "a";
serial.write(output);
serial.flush();
timer.start();
// Sleep(80);
qDebug() << timer.elapsed();
serial.waitForBytesWritten(100);
serial.waitForReadyRead(100);
if(serial.bytesAvailable()>=18)
input = serial.read(18);
qDebug()<<input;
}
}
return a.exec();
}
The answer to your question is in the following code:
QByteArray ba("J");
serial.write(ba);
serial.flush();
qDebug() << "data has been send" << endl;
serial.close();
After you make serial.flush (), you immediately close the port. It is necessary to wait until the data is really sent. For example, using bool QSerialPort :: waitForBytesWritten (int msecs).

Double way Serial communication between Arduino and Qt 5.7

I am trying to transfer data from Arduino to a C++ Qt5.7 and from a Arduino to a C++ Qt5.7 (MinGW) program.
I am able to transfer the data FROM QT TO ARDUINO without any problems.
The Arduino blinks perfectly.
On the other hand, the data transfered FROM THE ARDUINO TO QT isnt always the expected (sends "LED ON" when it should be "LED OFF") and sometimes it doesnt communicate at all!
QT code:
#include <QCoreApplication>
#include <QDebug>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QThread>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QSerialPort serial;
serial.setPortName("COM6");
serial.setBaudRate(9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
if(serial.open(QSerialPort::ReadWrite))
{
string c;
QByteArray s;
QByteArray received;
while(true)
{
qDebug("TRUE");
//WRITE
cin >> c;
cout << endl;
s = QByteArray::fromStdString(c);
serial.write(s);
serial.waitForBytesWritten(-1);
//serial.flush();
s = serial.readAll();
serial.waitForReadyRead(-1);
cout << s.toStdString() << endl;
//serial.flush();
}
}
else
{
QString error = serial.errorString();
cout << error.toStdString() << endl;
qDebug("FALSE") ;
}
serial.close();
return a.exec();
}
The ARDUINO CODE:
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
}
// the loop function runs over and over again forever
void loop() {
delay(1000); // wait for a second
}
void serialEvent()
{
char inChar;
while (Serial.available())
{
// get the new byte:
inChar = (char)Serial.read();
if(inChar == 'a')
{
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
}
else
{
digitalWrite(LED_BUILTIN, LOW); // turn the LED off (LOW is the voltage level)
}
}
delay(500);
if(inChar == 'a')
{
Serial.write("LED ON");
}
else
{
Serial.write("LED OFF");
}
}
Terminal Image of Error:
TERMINAL WITH ERROR image
Please help!
Thank you,
You have no packetization whatsoever: there are no delimiters between individual chunks of data - other than time passing.
On the Arudino side, instead of write, you should use println so that each message is a complete line.
On the Qt side, process complete lines. You're not guaranteed to get a complete response from the serial port after waitForReadyRead. All that you're guaranteed is that at least 1 byte is available to read. That is the source of your problem. Note how you got LE, then sometime later you got D OFF immediately followed by LED ON. You must wait for data until complete line(s) are available.
The following should work on the Qt end of things - also note that you don't need as many includes, and you can use QTextStream instead of iostream, to lower the number of APIs that you use. Finally, you don't need app.exec since you write blocking code.
// https://github.com/KubaO/stackoverflown/tree/master/questions/arduino-read-40246601
#include <QtSerialPort>
#include <cstdio>
int main(int argc, char *argv[])
{
QCoreApplication a{argc, argv};
QTextStream in{stdin};
QTextStream out{stdout};
QSerialPort port;
port.setPortName("COM6");
port.setBaudRate(9600);
port.setDataBits(QSerialPort::Data8);
port.setParity(QSerialPort::NoParity);
port.setStopBits(QSerialPort::OneStop);
port.setFlowControl(QSerialPort::NoFlowControl);
if (!port.open(QSerialPort::ReadWrite)) {
out << "Error opening serial port: " << port.errorString() << endl;
return 1;
}
while(true)
{
out << "> ";
auto cmd = in.readLine().toLatin1();
if (cmd.length() < 1)
continue;
port.write(cmd);
while (!port.canReadLine())
port.waitForReadyRead(-1);
while (port.canReadLine())
out << "< " << port.readLine(); // lines are already terminated
}
}
If you wish, you can also easily turn it into a GUI application, it's only a few lines to do so:
#include <QtSerialPort>
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication app{argc, argv};
QWidget ui;
QFormLayout layout{&ui};
QLineEdit portName{"COM6"};
QTextBrowser term;
QLineEdit command;
QPushButton open{"Open"};
layout.addRow("Port", &portName);
layout.addRow(&term);
layout.addRow("Command:", &command);
layout.addRow(&open);
ui.show();
QSerialPort port;
port.setBaudRate(9600);
port.setDataBits(QSerialPort::Data8);
port.setParity(QSerialPort::NoParity);
port.setStopBits(QSerialPort::OneStop);
port.setFlowControl(QSerialPort::NoFlowControl);
QObject::connect(&open, &QPushButton::clicked, &port, [&]{
port.setPortName(portName.text());
if (port.open(QSerialPort::ReadWrite)) return;
term.append(QStringLiteral("* Error opening serial port: %1").arg(port.errorString()));
});
QObject::connect(&command, &QLineEdit::returnPressed, &port, [&]{
term.append(QStringLiteral("> %1").arg(command.text()));
port.write(command.text().toLatin1());
});
QObject::connect(&port, &QIODevice::readyRead, &term, [&]{
if (!port.canReadLine()) return;
while (port.canReadLine())
term.append(QStringLiteral("< %1").arg(QString::fromLatin1(port.readLine())));
});
return app.exec();
}
I think you must use EOL and Carrige return character on QT. Try to replace Serial.write to Serial.println in Arduino code.

Qt freeing memory

I wrote a C++ program in Qt that used dynamic memory allocation, and I made sure to include the free() call at the end. However, when the program reaches the free statement, it crashes. (I know this because the test that I added never printed after the free statements) Anyway, here's the code:
#include <QCoreApplication>
#include <QSerialPort>
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <Windows.h>
using namespace std;
int main(int argc, char *argv[])
{
QSerialPort serial0;
//serial.open(serial);
serial0.setBaudRate(QSerialPort::Baud9600);
serial0.setDataBits(QSerialPort::Data8);
serial0.setParity(QSerialPort::NoParity);
serial0.setStopBits(QSerialPort::OneStop);
serial0.setFlowControl(QSerialPort::NoFlowControl);
char *com="com";
int number;
char *comPlusNumber;
comPlusNumber=(char*) malloc(8*sizeof(char));
int j=10000;
while(j>0)
{
number=j;
sprintf(comPlusNumber, "%s%d",com,number);
//printf("%s \n",comPlusNumber);
serial0.setPortName(comPlusNumber);
serial0.open(QIODevice::ReadWrite);
if(serial0.isOpen()==true)
{
printf("YES*****************");
printf("%s \n",comPlusNumber);
}
else
//printf("No %d\n", number);
serial0.close();
j--;
}
free(com);
free(comPlusNumber);
printf("\n\n Test");
//QCoreApplication a(argc, argv);
//return a.exec();
}
I just wanted to make sure that I wasn't creating a memory leak.
Use the framework. You've got the power of Qt!
There are several problems:
The C-style string manipulations are unnecessary and wrong. Use QString:
auto name = QStringLiteral("COM%1").arg(i);
You can't use the serial port without a QCoreApplication instance present.
You shouldn't be testing for the presence of a port by iterating what you think might be valid ports. This is non-portable and unnecessary. Get a list of ports to start with.
Thus:
// https://github.com/KubaO/stackoverflown/tree/master/questions/simple-serial-35181906
#include <QtCore>
#include <QtSerialPort>
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
QSerialPort serial;
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
for (auto port : QSerialPortInfo::availablePorts()) {
serial.setPort(port);
serial.open(QIODevice::ReadWrite);
if (serial.isOpen()) {
qDebug() << "port" << port.portName() << "is open";
serial.close();
} else
qDebug() << "port" << port.portName() << "couldn't be opened";
}
}
Here's the output on my machine:
port "cu.serial1" is open
port "cu.usbserial-FTELA9I5" is open
port "cu.usbserial-PX9A3C3B" is open
You can only free what you dynamically allocated. You never dynamically allocated anything for com, so passing it to free is an error. It's equivalent to free("com"); which attempts to free a string constant.

Qt serial port program crashes when run on another system

I modified this code on a Windows 10 PC, and it compiled and ran without crashing.
#include <QtSerialPort/QSerialPort>
#include <QTextStream>
#include <QCoreApplication>
#include <QFile>
#include <QStringList>
QT_USE_NAMESPACE
int main(int argc, char *argv[])
{
QCoreApplication coreApplication(argc, argv);
int argumentCount = QCoreApplication::arguments().size();
QStringList argumentList = QCoreApplication::arguments();
QTextStream standardOutput(stdout);
if (argumentCount == 1) {
standardOutput << QObject::tr("Usage: %1 <serialportname> [baudrate]").arg(argumentList.first()) << endl;
return 1;
}
QSerialPort serialPort;
QString serialPortName = argumentList.at(1);
serialPort.setPortName(serialPortName);
int serialPortBaudRate = (argumentCount > 2) ? argumentList.at(2).toInt() : QSerialPort::Baud9600;
serialPort.setBaudRate(serialPortBaudRate);
if (!serialPort.open(QIODevice::WriteOnly)) {
standardOutput << QObject::tr("Failed to open port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
QFile dataFile("C:\\SerialCommand.dat");
if (!dataFile.open(QIODevice::ReadOnly)) {
standardOutput << QObject::tr("Failed to open file for reading") << endl;
return 1;
}
QByteArray writeData(dataFile.readAll());
dataFile.close();
if (writeData.isEmpty()) {
standardOutput << QObject::tr("Either no data was currently available on the standard input for reading, or an error occurred for port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
qint64 bytesWritten = serialPort.write(writeData);
if (bytesWritten == -1) {
standardOutput << QObject::tr("Failed to write the data to port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
} else if (bytesWritten != writeData.size()) {
standardOutput << QObject::tr("Failed to write all the data to port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
} else if (!serialPort.waitForBytesWritten(5000)) {
standardOutput << QObject::tr("Operation timed out or an error occurred for port %1, error: %2").arg(serialPortName).arg(serialPort.errorString()) << endl;
return 1;
}
standardOutput << QObject::tr("Data successfully sent to port %1").arg(serialPortName) << endl;
printf("\n\ntest");
return 0;
}
I set Qt to release mode, and packaged the application with the following .dll files:
msvcp120d.dll
msvcr120d.dll
Qt5Core.dll
Qt5Cored.dll
Qt5SerialPort.dll
Qt5SerialPortd.dll
Qt5Widgets.dll
qwindows.dll
When I ran the application on another system (also windows 10), the program crashes immediately - and yes, I did move SerialCommand.dat to its correct location on the C drive. Any thoughts?
You're packaging the debug versions of the dlls (ending with a d) instead of release ones.
Read the Qt deployment docs, especially the last part (from "Application Dependencies" to the end).
The dependency walker helps find the actual dependencies, and in theory windeployqt should automate the work of creating a release dir with all the files you need.
See also this other question, but it's for an app using QML, so it's more complex than your case.

qt serial receiver missing data

I am trying to read my SerialPort based on the
http://doc.qt.io/qt-5/qtserialport-creadersync-main-cpp.html
example:
QCoreApplication coreApplication(argc, argv);
QTextStream standardOutput(stdout);
QSerialPort serialPort;
QByteArray readData;
serialPort.setPortName("ttyS4");
serialPort.setBaudRate(QSerialPort::Baud9600);
serialPort.setDataBits(QSerialPort::Data8);
serialPort.setParity(QSerialPort::EvenParity);
serialPort.setStopBits(QSerialPort::OneStop);
serialPort.setFlowControl(QSerialPort::NoFlowControl);
if (!serialPort.open(QIODevice::ReadOnly)) {
standardOutput << QObject::tr("Failed to open port") << endl;
return 1;
}
while (serialPort.waitForReadyRead(5000))
readData.append(serialPort.readAll());
qDebug() << readData;
return coreApplication.exec();
I also tried reading Data based on the http://doc.qt.io/qt-5/qtserialport-cwriterasync-example.html example:
Main:
int main(int argc, char *argv[])
{
QCoreApplication coreApplication(argc, argv);
QTextStream standardOutput(stdout);
QSerialPort serialPort;
serialPort.setPortName("ttyS4");
serialPort.setBaudRate(QSerialPort::Baud9600);
serialPort.setDataBits(QSerialPort::Data8);
serialPort.setParity(QSerialPort::EvenParity);
serialPort.setStopBits(QSerialPort::OneStop);
serialPort.setFlowControl(QSerialPort::NoFlowControl);
if (!serialPort.open(QIODevice::ReadOnly)) {
standardOutput << QObject::tr("Failed to open port") << endl;
return 1;
}
SerialPortReader serialPortReader(&serialPort);
return coreApplication.exec();
}
serialPortReader:
SerialPortReader::SerialPortReader(QSerialPort *serialPort, QObject *parent):QObject(parent), m_serialPort(serialPort), m_standardOutput(stdout)
{
connect(m_serialPort, SIGNAL(readyRead()), SLOT(handleReadyRead()));
connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), SLOT(handleError(QSerialPort::SerialPortError)));
connect(&m_timer, SIGNAL(timeout()), SLOT(handleTimeout()));
m_counter = 0;
m_timer.start(5000);
}
SerialPortReader::~SerialPortReader()
{
}
void SerialPortReader::handleReadyRead()
{ m_counter++;
m_readData.append(m_serialPort->readAll());
qDebug()<< m_serialPort->readAll();
qDebug() << "triggered" << m_counter;
}
void SerialPortReader::handleTimeout()
{
if (m_readData.isEmpty()) {
m_standardOutput << QObject::tr("No data was currently available for reading from port %1").arg(m_serialPort->portName()) << endl;
} else {
m_standardOutput << QObject::tr("Data successfully received from port %1").arg(m_serialPort->portName()) << endl;
m_standardOutput << m_readData << endl;
}
QCoreApplication::quit();
}
void SerialPortReader::handleError(QSerialPort::SerialPortError serialPortError)
{
if (serialPortError == QSerialPort::ReadError) {
m_standardOutput << QObject::tr("An I/O error occurred while reading the data from port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl;
QCoreApplication::exit(1);
}
}
But when I send data to this COM port (with same serialPort Settings for Sender), not all of the data is received.
With the MSB-RS232 I can check which data really has been sendet to the port and there is nothing wrong with my sender.
For testing I am sending
main:
QString alpha = "abcdefghijklmnopqrstuvwxyz123456789";
handler.writetoPort(alpha);
handler.cpp:
void SerialHandler::writetoPort(QString x)
{
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QByteArray encodedVar = codec->fromUnicode(x);
writetoPort(encodedVar);
}
void SerialHandler::writetoPort(const QByteArray x)
{
serial.write(x);
serial.waitForBytesWritten(-1);
}
The result of this is the output:
abyz123456789 or abcdklmnopqrstuvwxyz123456789 or abcdefghijklm or ...
It's always different.
Does anyone have a clue what is going on here?
Thank you for reading my long post.
--added 17.07--
This might be mandatory for my problem:
The code has to run on a microprocessor.
CPU: Atmel -AT91SAM9X25 - ARM926(ARMv5) - 400MHz
RAM: 32 MB
Linux Kernel Version: 3.9.0
QT Version: 5.4.1 (cross compiled)
both the async and sync example are working perfectly fine on my Windows PC.
Maybe this will help
void SerialPortReader::handleReadyRead()
{
m_counter++;
while (m_serialPort->bytesAvailable())
{
m_readData.append(m_serialPort->readAll());
}
qDebug()<< m_readData;
qDebug() << "triggered" << m_counter;
}
I tried the exact same Projekt on a different Board and everything works smoothly.
I think the COM Port of the old Board might have been damaged.
Will mark this as resolved but I can't tell what the true problem really was.