日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt ModbusTCP ModbusRTU 使用同步读和异步写

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt ModbusTCP ModbusRTU 使用同步读和异步写 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用Qt自帶的庫開發,添加相關頭文件

#include <QModbusTcpClient> #include <QModbusReply> #include <QSerialPort> #include <QModbusDataUnit> #include <QModbusRtuSerialMaster>

一、寄存器說明

Modbus寄存器的操作包括讀寫和只讀。具體如下:

enum RegisterType {Invalid,DiscreteInputs,Coils,InputRegisters,HoldingRegisters};

分別叫做:

  • 離散輸入寄存器(只讀,通常為開關量輸入)
  • 線圈寄存器(讀寫,一般為繼電器的控制)
  • 輸入寄存器(只讀,一般為模擬量輸入)
  • 保持寄存器(讀寫,一般狀態參數控制)

二、同步讀取

QT采用事件處理機制,由于Modbus讀取過程通常有時延,Qt機制不適合采用while延時等待讀取的方式。網上大多采用的是基于ModbusReply的Finished信號,做異步處理。導致在獲取寄存器數據時候比較麻煩。因此,可以考慮使用事件循環做同步處理。

讀寄存器數據的接口:

QVector<quint16> MainWindow::readModbusTcpUnit(QModbusDataUnit::RegisterType type, int startAddr, int numbers, int serverID, bool *isOK)
  • type:指明讀取的類型,由RegisterType類型定義
  • startAddr:起始地址
  • numbers:讀取的數量
  • serverID:服務器的ID
  • isOK:當前操作是否成功
  • 返回值:QVector<quint16> 類型,讀取的數據放在向量中?

以下是具體實現:

QVector<quint16> MainWindow::readModbusTcpUnit(QModbusDataUnit::RegisterType type, int startAddr, int numbers, int serverID, bool *isOK) {QVector<quint16> results;results.clear();if (mModbusClient->state() != QModbusDevice::ConnectedState) {*isOK = false;return results;}QModbusDataUnit readUnit(type, startAddr, static_cast<quint16>(numbers));auto *reply = mModbusClient->sendReadRequest(readUnit, serverID);if (!reply->isFinished()) {QEventLoop loop;connect(reply, &QModbusReply::finished,&loop,&QEventLoop::quit);eventLoop.exec();}if (reply->error() == QModbusDevice::NoError) {const QModbusDataUnit unit = reply->result();QString strType;switch (type){case QModbusDataUnit::Coils: strType = "Coils"; break;case QModbusDataUnit::DiscreteInputs: strType = "DiscreteInputs"; break;case QModbusDataUnit::HoldingRegisters: strType = "HoldingRegisters"; break;case QModbusDataUnit::InputRegisters: strType = "InputRegisters"; break;}qDebug()<<"read "<<strType<< " startAddr = "<<startAddr<<" numbers = "<<numbers<<" values = " <<unit.values();*isOK = true;results = unit.values();} else {*isOK = false;}delete reply;return results; }

使用方法:

/** bool isOK;* QVector<quint16> readUnit = readModbusTcpUnit(QModbusDataUnit::Coils, 0, 10, SERVER_ID, &isOK);* QVector<quint16> readUnit = readModbusTcpUnit(QModbusDataUnit::DiscreteInputs, 0, 10, SERVER_ID, &isOK);* QVector<quint16> readUnit = readModbusTcpUnit(QModbusDataUnit::HoldingRegisters, 0, 10, SERVER_ID, &isOK);* QVector<quint16> readUnit = readModbusTcpUnit(QModbusDataUnit::InputRegisters, 0, 10, SERVER_ID, &isOK); */

三、異步寫

寫寄存器只有Coils和HoldingRegisters可以操作,寫操作使用異步執行。

接口如下:

bool MainWindow::writeModbusTcpCoils(QVector<quint16> coilsValues, int startAddr, int numbers, int serverID)
  • coilsValues:向量,需要寫入的值;
  • startAddr:起始地址
  • numbers:需要寫寄存器的數量
  • serverID:服務器的ID

以寫線圈為例,實現如下:

void MainWindow::writeModbusTcpCoils(QVector<quint16> coilsValues, int startAddr, int numbers, int serverID) {if (coilsValues.size() < numbers){qDebug()<<"error : coilsValue size < numbers";return;}if (mModbusClient->state() != QModbusDevice::ConnectedState) {qDebug()<<"error : disConnectedState";return;}QModbusDataUnit writeUnit(QModbusDataUnit::Coils, startAddr, static_cast<quint16>(numbers));for (int valueIdx = 0; valueIdx < writeUnit.valueCount(); ++valueIdx) {writeUnit.setValue(valueIdx, coilsValues.at(valueIdx));}auto *reply = mModbusClient->sendWriteRequest(writeUnit, serverID);if (!reply->isFinished()) {connect(reply, &QModbusReply::finished, this, [this, reply]() {if (reply->error() == QModbusDevice::ProtocolError) {qDebug() << “ProtocolError”;} else if (reply->error() != QModbusDevice::NoError) {qDebug() << “Error”;}});}reply->deleteLater(); }

使用方法:

/** QVector<quint16> values;* values.push_back(1);* values.push_back(0);* values.push_back(1);* writeModbusTcpCoils(values, 0, 3, SERVER_ID);* writeModbusTcpCoils(values, 3, 2, SERVER_ID); */

寫保持寄存器和寫線圈類似,不在贅述。

總結

以上是生活随笔為你收集整理的Qt ModbusTCP ModbusRTU 使用同步读和异步写的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。