2017-07-28 13 views
0

私の問題は、私のコードがコントローラへの接続からデータを受信するのを止める理由がわかりません。Qt/C++でModbus-RTUプロトコルを使用してデバイスに接続する

状況:私はデバイスに接続してデータを取得するためのQtプログラムを作成しています。このデバイスは、ボーレート9600、偶数パリティ、8データビット、1ストップビットのModbus-RTUプロトコルを使用してRS-485でデータを転送します。 QtプログラムはQSerialPortクラスを使用してデバイスと通信します。プログラムを初めて起動したときに、バイナリパケットを送信した後、デバイスからの応答を受け取ることができます。しかし、2回目からは、私のプログラムは何も受信しません。でも、上記のパケットをたくさん送信しました。理解を容易にするために、以下の私のコードを確認してください:

01030000000ac5cd 
Length: 8 


Length: 0 

0103140000001b0000000000000000ffb2000400040000b49e 
Length: 25 

01030000000ac5cd 
Length: 8 


Length: 0 

01030000000ac5cd 
Length: 8 


Length: 0 

01030000000ac5cd 
Length: 8 

が、私は私のコードで何かを見逃していました:

#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); 
      do { 
       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(); 
} 

ここで私が得た結果ですか?

ありがとうございました。

+1

あなたは、デバッガを使用して参照しようとしたことがあり何が起こっている? –

答えて

0

私のコードで何かを忘れましたか?

少なくとも、エラーチェックを見逃しました。

あなたのデバイスが誤動作しているかどうかを知ることも難しいです。

その他のニックネームは暗黙的なフラッシュを実行するので、flushは不要です。 _sleepも不要です:最後に失敗したwaitForReadyReadは3秒間待機します。ログファイルを再オープンするかどうかは疑問です。おそらくflush()にしたいのですか?最後に、<QtModule/QClass> includesを使用しないでください。リンク時にプロジェクト構成エラーが発生します。 <QClass>のみを使用するか、またはQtモジュール全体を含めるには<QtModule>を使用します。

たとえば、あなたが投稿やや複雑なので、おそらくエラーチェックと、この読みやすいバージョンは、それが可能あなたが間違っているものを把握するために行います:

// 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 the 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 the 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); 
     do { 
     receive(port, log); 
     } while (port.waitForReadyRead(3000)); 
    } 
} 
関連する問題