windows - Connect to a device using Modbus-RTU protocol with Qt/C++ -
my problem don't know why code stop receiving data connection controller.
situation: i'm writing qt program connect , data device. device uses modbus-rtu protocol baudrates 9600, parity, 8 databits, 1 stopbit transfer data on rs-485. qt program use qserialport class communicate device. in first time start program, can receive reply device after sent binary packet. second time, program doesn't receive anything, sent lot of same packets above. please check code below easier understanding:
#include <qcoreapplication> #include <qtserialport/qserialport.h> #include <qtserialport/qserialport> #include <iostream> #include <bitset> #include <fstream> using namespace std; int main(int argc, char *argv[]) { qcoreapplication a(argc, argv); fstream fs; qserialport qsp; qsp.setportname("com2"); qsp.setbaudrate(qserialport::baud9600); qsp.setdatabits(qserialport::data8); qsp.setparity(qserialport::evenparity); qsp.setstopbits(qserialport::onestop); qsp.setflowcontrol(qserialport::noflowcontrol); if (qsp.open(qiodevice::readwrite)){ qbytearray qbadatasend; qbadatasend.resize(8); qbadatasend[0] = 0x01; qbadatasend[1] = 0x03; qbadatasend[2] = 0x00; qbadatasend[3] = 0x00; qbadatasend[4] = 0x00; qbadatasend[5] = 0x0a; qbadatasend[6] = 0xc5; qbadatasend[7] = 0xcd; cout << endl << "byte wrote: " <<qbadatasend.tohex().tostdstring() << endl << "length: " << qsp.write(qbadatasend) << endl; fs.open("data.txt", ios_base::app | ios_base::out); fs << qbadatasend.tohex().tostdstring() << endl; fs << "length: " << qbadatasend.tostdstring().length() << endl << endl; fs.close(); qsp.flush(); while(true){ _sleep(3000); { qbytearray qbadataread = qsp.readall(); fs.open("data.txt", ios_base::app | ios_base::out); cout << qbadataread.tohex().tostdstring() << endl; fs << qbadataread.tohex().tostdstring() << endl; cout << "length: " << qbadataread.tostdstring().length() << endl << endl; fs << "length: " << qbadataread.tostdstring().length() << endl << endl; fs.close(); } while(qsp.waitforreadyread(3000)); cout << endl << "byte wrote: " <<qbadatasend.tohex().tostdstring() << endl << "length: " << qsp.write(qbadatasend) << endl; qsp.write(qbadatasend, 8); fs.open("data.txt", ios_base::app | ios_base::out); fs << qbadatasend.tohex().tostdstring() << endl; fs << "length: " << qbadatasend.tostdstring().length() << endl << endl; fs.close(); qsp.flush(); } } cout << "out" << endl; qsp.close(); cout << "error: " << qsp.errorstring().tostdstring() << endl; cout << "close" << endl; return a.exec(); }
here's result got:
01030000000ac5cd length: 8 length: 0 0103140000001b0000000000000000ffb2000400040000b49e length: 25 01030000000ac5cd length: 8 length: 0 01030000000ac5cd length: 8 length: 0 01030000000ac5cd length: 8
did miss in code?
thanks.
did miss in code?
at least missed error checking.
it's hard tell whether device may malfunctioning or not.
other nitpicks: flush
unnecessary since waitforreadyread
performs implicit flush. _sleep
unnecessary well: last, failing waitforreadyread
wait 3 seconds. it's questionable whether wish re-opening log file - perhaps wish flush()
it? finally, not use <qtmodule/qclass>
includes - defer project configuration errors link time. use <qclass>
includes only, or include entire qt module use <qtmodule>
.
the example posted convoluted, perhaps easier-to-read version error checking make possible figure what's wrong:
// https://github.com/kubao/stackoverflown/tree/master/questions/serial-blocking-45369860 #include <qtserialport> template <class t> bool haserror(const qiodevice & d) { return qobject_cast<const t *>(&d) && static_cast<const t &>(d).error() != t::noerror; } void chkerror(const qiodevice & d) { if (haserror<qfile>(d) || haserror<qserialport>(d)) qfatal("i/o error on %s: %s", d.objectname().tolocal8bit().constdata(), d.errorstring().tolocal8bit().constdata()); } void logdata(qtextstream & log, const qbytearray & data) { log << data.tohex() << "\nlength: " << data.size() << "\n\n"; log.flush(); chkerror(*log.device()); } void transmit(qserialport & port, const qbytearray & data, qtextstream & log) { port.write(data); qdebug() << "\nwrote" << data.size() << ":" << data.tohex().constdata(); chkerror(port); logdata(log, data); } void receive(qserialport & port, qtextstream & log) { auto data = port.readall(); qdebug() << "\nread" << data.size() << ":" << data.tohex().constdata(); chkerror(port); logdata(log, data); } int main(int argc, char *argv[]) { qcoreapplication app(argc, argv); qfile logfile("data.txt"); if (!logfile.open(qiodevice::writeonly | qiodevice::append | qiodevice::text)) qfatal("can't open log file: %s", logfile.errorstring().tolocal8bit().constdata()); qtextstream log(&logfile); qserialport port; port.setportname("com2"); port.setbaudrate(qserialport::baud9600); port.setdatabits(qserialport::data8); port.setparity(qserialport::evenparity); port.setstopbits(qserialport::onestop); port.setflowcontrol(qserialport::noflowcontrol); if (!port.open(qiodevice::readwrite)) qfatal("can't open serial port: %s", port.errorstring().tolocal8bit().constdata()); logfile.setobjectname("log file"); port.setobjectname("serial port"); const qbytearray sendpacket = qbytearrayliteral("\x01\x03\x00\x00\x00\x0a\0xc5\x0cd"); while (true) { transmit(port, sendpacket, log); { receive(port, log); } while (port.waitforreadyread(3000)); } }
Comments
Post a Comment