PDA

View Full Version : COM-port in Qt



Victor007
22nd July 2013, 16:38
Hello! I have several functions for working with COM-port. Here is a small listing, that I used in C++ Builder:



//function for opening COM-port
void COMOpen(portname)
{
DCB dcb;
COMMTIMEOUTS timeouts; //structure for timeouts

//open COM-port!
COMport = CreateFile(portname.c_str(),GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

if(COMport == INVALID_HANDLE_VALUE) { //if error
QMessageBox::warning(this, "Error", "No such COM!");
return;
}
}

//function for closing COM-port
void COMClose()
{
CloseHandle(COMport);
COMport=0;
handle=0;
}


on_pushButton_clicked() // function send pulse on button click
{
COMOpen(portname); //initialized and open port

int i;
EscapeCommFunction(COMport, SETDTR); //set hight level DTR
ui->label->setText("Sending pulse to com-port..."); //sign about sending pulse
i=0;
while (i<3000000) { // wait a little, pulse should have a duration
i++;
Application->ProcessMessages();
}
EscapeCommFunction(COMport, CLRDTR); // free DTR pin
ui->label->setText(""); //pulse finished, so remove label
COMClose(portname); //close COM-port

}


When I include the code to Qt creator I get errors. I'm novice in Qt. Could someone make simple example, which open COM1, for instance, with this code? Thanks a lot!

anda_skoa
22nd July 2013, 18:09
Hi,
I am novice in mind reading. Could you probably tell us which errors you are getting?

Cheers,
_

Victor007
22nd July 2013, 18:54
Sorry, it's too many errors. I should replace this Application->CreateForm in WinApi to something like a->Initialize(), but now it's just conguring. Sorry for low skill. I think, it's better to attache my project.

kuzulis
22nd July 2013, 19:18
You can try the ready module: QtSerialPort (http://qt-project.org/wiki/QtSerialPort)

Online documentation: http://qt-project.org/doc/qt-5.1/qtserialport/qserialport.html

Then your solution was like:



class MyClass : public QObject
{
public:
explicit MyClass() {
port = new QSerialPort(this);
port->setPortName("COM1");
connect(port, SIGNAL(dataTerminalReadyChanged(bool)), this, SLOT(onDtr(bool)));

timer = new QTimer(this);
timer->setSingleShot();
connect(timer, SIGNAL(timeout()), this, SLOT(onTimer()));
}

void startPulse() {
if (!port->open(QIODevice::ReadWrite))
return;

port->setDataTerminalReady(true);
}

private slots:
void onTimer() {
port->setDataTerminalReady(false);
}

void onDtr(bool set) {
if (set) {
timer->start(50); // ~50msec :)
} else {
port->close();
}
}

private:
QSerialPort *port;
QTimer *timer;
}

Victor007
22nd July 2013, 23:45
Thank you, but it doesn't work on my computer. Fist problem is that my qt creator doesn't know qextserialport.h. How can I add it or what #include do I need if not that?
And why do you use dataTerminalReadyChanged(bool) signal? I need only set DTR on push button, so should I just call onDtr() function in push_button case, right? I don't need connect(port, SIGNAL(dataTerminalReadyChanged(bool)), this, SLOT(onDtr(bool))), do I?

ChrisW67
23rd July 2013, 00:13
I don't see how this:

Fist problem is that my qt creator doesn't know qextserialport.h.
is related to this:

You can try the ready module: QtSerialPort
They are two different components. QtSerialPort is a part of Qt 5.1 out-of-the-box, QExtSerialPort is external.

You use external libraries by including the relevant INCLUDEPATH and LIBS entries in your PRO file.
Declaring Other Libraries


And why do you use dataTerminalReadyChanged(bool) signal? I need only set DTR on push button, so should I just call onDtr() function in push_button case, right? I don't need connect(port, SIGNAL(dataTerminalReadyChanged(bool)), this, SLOT(onDtr(bool))), do I?

The signal dataTerminalReadyChanged() signal connection ensures that regardless of how DTR is turned on the timer is started. The connection to the timer signal ensures that DTR is turned off approximately 50 mSec later. You can arrange it differently if you wish.

Victor007
23rd July 2013, 13:30
Thanks again. Unfortunately, I have Qt 4.8.3 and need solution directly for this version. I've read the documentation and obtained, that I should include this line to my pro file: CONFIG += serialport After all, I still have too many mistakes.

ChrisW67
23rd July 2013, 23:03
I've read the documentation and obtained, that I should include this line to my pro file: CONFIG += serialport
That's the documentation for QtSerialPort (http://qt-project.org/wiki/QtSerialPort).
The instructions for QExtSerialPort (http://code.google.com/p/qextserialport/source/browse/README) are different.
You can build either for Qt 4 but you implied you were trying to use QExtSerialPort.

Victor007
27th July 2013, 18:20
Thank you! Now I'm much more close to the solution. I use 3rd way from wiki, include to my .pro:



INCLUDEPATH += C:/qextserialport-1.2/src
LIBS += -L C:/qextserialport-1.2/lib -lqextsrialport-1.2
DEFINES += QEXTSERIALPORT_USING_SHARED


I've truncated my code and left just the open/close procedure by press Button. Now I have only unique error:

:-1: error: LNK1146: no argument specified with option '/LIBPATH:'

And I really do not see any lib path in the proper directory. But I used instructions and download the directory from one issue that you wrote (instructions for QExtSerialPort (https://code.google.com/p/qextserialport/wiki/Downloads?tm=2))

Victor007
28th July 2013, 18:00
I also tried first way with including qextserialport.pri in .pro file, but now I have other errors:


moc_widget.obj:-1: error: LNK2019: unresolved external symbol "private: void __cdecl Widget:: onPortAddedOrRemoved(void)" (?onPortAddedOrRemoved@Widget@@AEAAXXZ) referenced in function "private: static void __cdecl Widget::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void (?qt_static_metacall@Widget@@CAXPEAVQObject@@W4Cal l@QMetaObject@@HPEAPEAX@Z)

Shit! What can be wrong?! I use so minimal code:


#include "widget.h"
#include "ui_widget.h"
#include "qextserialport.h"
#include <QtCore>

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
PortSettings settings = {BAUD9600, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 10};
port = new QextSerialPort("COM1", settings, QextSerialPort::Polling);
}

Widget::~Widget()
{
delete ui;
}

void Widget::on_pushButton_clicked()
{
if (!port->isOpen()) {
port->setPortName("COM1");
port->open(QIODevice::ReadWrite);
}
else {
port->close();
}
}

anda_skoa
29th July 2013, 08:41
The linker says it can't find Widget::onPortAddedOrRemoved()

Maybe you only have it in the header and not in the cpp file?

Cheers,
_

Victor007
29th July 2013, 09:43
Oh, y! Thank you very much, it works)