commit
d63d454cc5
8 changed files with 860 additions and 0 deletions
@ -0,0 +1,73 @@ |
|||||
|
# This file is used to ignore files which are generated |
||||
|
# ---------------------------------------------------------------------------- |
||||
|
|
||||
|
*~ |
||||
|
*.autosave |
||||
|
*.a |
||||
|
*.core |
||||
|
*.moc |
||||
|
*.o |
||||
|
*.obj |
||||
|
*.orig |
||||
|
*.rej |
||||
|
*.so |
||||
|
*.so.* |
||||
|
*_pch.h.cpp |
||||
|
*_resource.rc |
||||
|
*.qm |
||||
|
.#* |
||||
|
*.*# |
||||
|
core |
||||
|
!core/ |
||||
|
tags |
||||
|
.DS_Store |
||||
|
.directory |
||||
|
*.debug |
||||
|
Makefile* |
||||
|
*.prl |
||||
|
*.app |
||||
|
moc_*.cpp |
||||
|
ui_*.h |
||||
|
qrc_*.cpp |
||||
|
Thumbs.db |
||||
|
*.res |
||||
|
*.rc |
||||
|
/.qmake.cache |
||||
|
/.qmake.stash |
||||
|
|
||||
|
# qtcreator generated files |
||||
|
*.pro.user* |
||||
|
|
||||
|
# xemacs temporary files |
||||
|
*.flc |
||||
|
|
||||
|
# Vim temporary files |
||||
|
.*.swp |
||||
|
|
||||
|
# Visual Studio generated files |
||||
|
*.ib_pdb_index |
||||
|
*.idb |
||||
|
*.ilk |
||||
|
*.pdb |
||||
|
*.sln |
||||
|
*.suo |
||||
|
*.vcproj |
||||
|
*vcproj.*.*.user |
||||
|
*.ncb |
||||
|
*.sdf |
||||
|
*.opensdf |
||||
|
*.vcxproj |
||||
|
*vcxproj.* |
||||
|
|
||||
|
# MinGW generated files |
||||
|
*.Debug |
||||
|
*.Release |
||||
|
|
||||
|
# Python byte code |
||||
|
*.pyc |
||||
|
|
||||
|
# Binaries |
||||
|
# -------- |
||||
|
*.dll |
||||
|
*.exe |
||||
|
|
@ -0,0 +1,33 @@ |
|||||
|
QT += core gui serialbus |
||||
|
|
||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets |
||||
|
|
||||
|
CONFIG += c++11 |
||||
|
|
||||
|
# The following define makes your compiler emit warnings if you use |
||||
|
# any Qt feature that has been marked deprecated (the exact warnings |
||||
|
# depend on your compiler). Please consult the documentation of the |
||||
|
# deprecated API in order to know how to port your code away from it. |
||||
|
DEFINES += QT_DEPRECATED_WARNINGS |
||||
|
|
||||
|
# You can also make your code fail to compile if it uses deprecated APIs. |
||||
|
# In order to do so, uncomment the following line. |
||||
|
# You can also select to disable deprecated APIs only up to a certain version of Qt. |
||||
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 |
||||
|
|
||||
|
SOURCES += \ |
||||
|
main.cpp \ |
||||
|
mainwindow.cpp \ |
||||
|
mymodbustcp.cpp |
||||
|
|
||||
|
HEADERS += \ |
||||
|
mainwindow.h \ |
||||
|
mymodbustcp.h |
||||
|
|
||||
|
FORMS += \ |
||||
|
mainwindow.ui |
||||
|
|
||||
|
# Default rules for deployment. |
||||
|
qnx: target.path = /tmp/$${TARGET}/bin |
||||
|
else: unix:!android: target.path = /opt/$${TARGET}/bin |
||||
|
!isEmpty(target.path): INSTALLS += target |
@ -0,0 +1,11 @@ |
|||||
|
#include "mainwindow.h" |
||||
|
|
||||
|
#include <QApplication> |
||||
|
|
||||
|
int main(int argc, char *argv[]) |
||||
|
{ |
||||
|
QApplication a(argc, argv); |
||||
|
MainWindow w; |
||||
|
w.show(); |
||||
|
return a.exec(); |
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
#include "mainwindow.h" |
||||
|
#include "ui_mainwindow.h" |
||||
|
|
||||
|
MainWindow::MainWindow(QWidget *parent) |
||||
|
: QMainWindow(parent) |
||||
|
, ui(new Ui::MainWindow) |
||||
|
{ |
||||
|
ui->setupUi(this); |
||||
|
modbusTcpClient = new MyModbusTcp(); |
||||
|
} |
||||
|
|
||||
|
MainWindow::~MainWindow() |
||||
|
{ |
||||
|
delete ui; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void MainWindow::on_connectBTN_clicked() |
||||
|
{ |
||||
|
modbusTcpClient->connectModbusTcp(); |
||||
|
} |
||||
|
|
||||
|
void MainWindow::on_disconnectBTN_clicked() |
||||
|
{ |
||||
|
modbusTcpClient->disconnectModbusTcp(); |
||||
|
} |
||||
|
|
||||
|
void MainWindow::on_ontimeBTN_clicked() |
||||
|
{ |
||||
|
// modbusTcpClient->onTimeReadHR();
|
||||
|
|
||||
|
timer1 = new QTimer(this); //启动定时器,100ms
|
||||
|
connect(timer1, SIGNAL(timeout()), this, SLOT(ontimeRead())); |
||||
|
timer1->start(100); // 每隔1000ms
|
||||
|
// modbusTcpClient->readMultipleHR(0,20,1);
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
void MainWindow::ontimeRead(){ |
||||
|
modbusTcpClient->readMultipleHR(0, 20, 1); |
||||
|
QString buf; |
||||
|
// int len = sizeof(modbusTcpClient->dataRCV)/sizeof(modbusTcpClient->dataRCV[0]);
|
||||
|
for(int i= 0; i<30; i++){ |
||||
|
buf.append(QString::number(modbusTcpClient->dataRCV[i])); |
||||
|
buf.append(" "); |
||||
|
} |
||||
|
ui->textEdit->setText(buf); |
||||
|
} |
||||
|
|
||||
|
void MainWindow::on_stopOntimeBTN_clicked() |
||||
|
{ |
||||
|
timer1->stop(); |
||||
|
timer1->deleteLater(); |
||||
|
} |
||||
|
|
||||
|
void MainWindow::on_pushButton_clicked() |
||||
|
{ |
||||
|
modbusTcpClient->writeSingleFloat(0, -3.14f, 1); |
||||
|
} |
||||
|
|
||||
|
void MainWindow::on_pushButton_2_clicked() |
||||
|
{ |
||||
|
float dataSend[3] = {0.0f, 1.1f, -2.3f}; |
||||
|
modbusTcpClient->writeMultipleHR(0, 6, dataSend, 1); |
||||
|
} |
@ -0,0 +1,50 @@ |
|||||
|
#ifndef MAINWINDOW_H |
||||
|
#define MAINWINDOW_H |
||||
|
|
||||
|
#include <QMainWindow> |
||||
|
#include "mymodbustcp.h" |
||||
|
|
||||
|
QT_BEGIN_NAMESPACE |
||||
|
namespace Ui { class MainWindow; } |
||||
|
QT_END_NAMESPACE |
||||
|
|
||||
|
class MainWindow : public QMainWindow |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
|
||||
|
public: |
||||
|
MainWindow(QWidget *parent = nullptr); |
||||
|
~MainWindow(); |
||||
|
QTimer *timer1; |
||||
|
MyModbusTcp *modbusTcpClient = nullptr; |
||||
|
|
||||
|
private slots: |
||||
|
/**
|
||||
|
* @brief on_connectBTN_clicked 连接 |
||||
|
*/ |
||||
|
void on_connectBTN_clicked(); |
||||
|
/**
|
||||
|
* @brief on_disconnectBTN_clicked 断开连接 |
||||
|
*/ |
||||
|
void on_disconnectBTN_clicked(); |
||||
|
/**
|
||||
|
* @brief on_ontimeBTN_clicked 持续读 |
||||
|
*/ |
||||
|
void on_ontimeBTN_clicked(); |
||||
|
/**
|
||||
|
* @brief on_stopOntimeBTN_clicked 停止读 |
||||
|
*/ |
||||
|
void on_stopOntimeBTN_clicked(); |
||||
|
/**
|
||||
|
* @brief ontimeRead 持续都写 |
||||
|
*/ |
||||
|
void ontimeRead(); |
||||
|
|
||||
|
void on_pushButton_clicked(); |
||||
|
|
||||
|
void on_pushButton_2_clicked(); |
||||
|
|
||||
|
private: |
||||
|
Ui::MainWindow *ui; |
||||
|
}; |
||||
|
#endif // MAINWINDOW_H
|
@ -0,0 +1,192 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>MainWindow</class> |
||||
|
<widget class="QMainWindow" name="MainWindow"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>800</width> |
||||
|
<height>600</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>MainWindow</string> |
||||
|
</property> |
||||
|
<widget class="QWidget" name="centralwidget"> |
||||
|
<layout class="QGridLayout" name="gridLayout"> |
||||
|
<item row="0" column="0"> |
||||
|
<widget class="QTextEdit" name="textEdit"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>300</width> |
||||
|
<height>100</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="1"> |
||||
|
<layout class="QVBoxLayout" name="verticalLayout"> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="connectBTN"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>150</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>300</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="font"> |
||||
|
<font> |
||||
|
<pointsize>14</pointsize> |
||||
|
</font> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>连接</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="disconnectBTN"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>150</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>300</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="font"> |
||||
|
<font> |
||||
|
<pointsize>14</pointsize> |
||||
|
</font> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>断开连接</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="ontimeBTN"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>150</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>300</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="font"> |
||||
|
<font> |
||||
|
<pointsize>14</pointsize> |
||||
|
</font> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>持续读</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="stopOntimeBTN"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>150</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>300</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="font"> |
||||
|
<font> |
||||
|
<pointsize>14</pointsize> |
||||
|
</font> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>停止持续读</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="pushButton"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>150</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>300</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="font"> |
||||
|
<font> |
||||
|
<pointsize>14</pointsize> |
||||
|
</font> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>写单个f</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="pushButton_2"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>150</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>300</width> |
||||
|
<height>50</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="font"> |
||||
|
<font> |
||||
|
<pointsize>14</pointsize> |
||||
|
</font> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>写多个</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<widget class="QMenuBar" name="menubar"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>800</width> |
||||
|
<height>21</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
</widget> |
||||
|
<widget class="QStatusBar" name="statusbar"/> |
||||
|
</widget> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
@ -0,0 +1,325 @@ |
|||||
|
#include "mymodbustcp.h" |
||||
|
|
||||
|
MyModbusTcp::MyModbusTcp() |
||||
|
{ |
||||
|
modbusDevice = new QModbusTcpClient(); |
||||
|
//有错误发生时,发出提示
|
||||
|
connect(modbusDevice, &QModbusClient::errorOccurred, this, &MyModbusTcp::errorOccurred_Slot); |
||||
|
//状态改变
|
||||
|
if(modbusDevice == nullptr){ |
||||
|
qDebug()<<"cannot create modbus client"; |
||||
|
} |
||||
|
else{ |
||||
|
connect(modbusDevice, &QModbusClient::stateChanged, this, &MyModbusTcp::stateChanged_SLot); |
||||
|
} |
||||
|
} |
||||
|
/**
|
||||
|
* @brief MyModbusTcp::timeGoBy 等待tms |
||||
|
* @param time |
||||
|
* @param t |
||||
|
*/ |
||||
|
void MyModbusTcp::timeGoBy(QTime time, int t){ |
||||
|
time.start(); //设定time为当前时间
|
||||
|
while(time.elapsed() < t){ //等待时间流逝500ms
|
||||
|
QCoreApplication::processEvents(); //处理事件
|
||||
|
} |
||||
|
} |
||||
|
//===================================数据类型转换===============================
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::float2Word 将浮点数f转化为2个8位数据存放在word数组中 |
||||
|
* @param f 待转换的浮点数 |
||||
|
* @param word 转换后的word数组 |
||||
|
*/ |
||||
|
void MyModbusTcp::float2Word(float f, unsigned int *word) |
||||
|
{ |
||||
|
unsigned long longdata = 0; |
||||
|
longdata = *(unsigned long*)&f; //注意,会丢失精度
|
||||
|
word[0] = (longdata & 0xFFFF0000) >> 16; |
||||
|
word[1] = (longdata & 0x0000FFFF); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::word2Float 将2个word数据转化为浮点数 |
||||
|
* @param p 指向word数组的指针 |
||||
|
* @param dataTransformed 转化后的浮点数 |
||||
|
*/ |
||||
|
void MyModbusTcp:: word2Float(unsigned int *p, float dataTransformed) |
||||
|
{ |
||||
|
dataTransformed=0; |
||||
|
unsigned long longdata = 0; |
||||
|
longdata = (*p<< 16) + (*(p+1) << 0); |
||||
|
dataTransformed = *(float*)&longdata; |
||||
|
} |
||||
|
|
||||
|
//==========================================modbustcp====================
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::errorOccurred_Slot 有错误发生 |
||||
|
*/ |
||||
|
void MyModbusTcp::errorOccurred_Slot(){ |
||||
|
qDebug()<<"new error"<<modbusDevice->errorString(); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::stateChanged_SLot 状态改变 |
||||
|
*/ |
||||
|
void MyModbusTcp::stateChanged_SLot(){ |
||||
|
if(modbusDevice->state() == QModbusDevice::UnconnectedState){ |
||||
|
qDebug()<<"Tcp Client未连接到server"; |
||||
|
} |
||||
|
else if(modbusDevice->state() == QModbusDevice::ConnectingState){ |
||||
|
qDebug()<<"正在连接"; |
||||
|
} |
||||
|
else if(modbusDevice->state() == QModbusDevice::ConnectedState){ |
||||
|
qDebug()<<"已连接"; |
||||
|
} |
||||
|
else if(modbusDevice->state() == QModbusDevice::ClosingState){ |
||||
|
qDebug()<<"已关闭"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::connectModbusTcp 连接ModbusTcp |
||||
|
*/ |
||||
|
void MyModbusTcp::connectModbusTcp() |
||||
|
{ |
||||
|
if(!modbusDevice){ |
||||
|
return; |
||||
|
} |
||||
|
if(modbusDevice->state() != QModbusDevice::ConnectedState){ |
||||
|
modbusDevice->setConnectionParameter(QModbusClient::NetworkAddressParameter,"192.168.9.71"); |
||||
|
modbusDevice->setConnectionParameter(QModbusClient::NetworkPortParameter,502); |
||||
|
modbusDevice->setTimeout(2000); //设置超时
|
||||
|
modbusDevice->setNumberOfRetries(3); //重试
|
||||
|
if(!modbusDevice->connectDevice()){ |
||||
|
qDebug()<<"连接失败"; |
||||
|
} |
||||
|
else { |
||||
|
qDebug()<<"连接成功"; |
||||
|
} |
||||
|
}else{ |
||||
|
// QMessageBox::information(this, "提示", "ModBusTcp已经连接");
|
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::disconnectModbusTcp 断开连接 |
||||
|
*/ |
||||
|
void MyModbusTcp::disconnectModbusTcp() |
||||
|
{ |
||||
|
if(modbusDevice->state() != QModbusDevice::ConnectedState){ |
||||
|
// QMessageBox::critical(this, "错误", "MosBusTcp未连接");
|
||||
|
return; |
||||
|
} |
||||
|
modbusDevice->disconnectDevice(); |
||||
|
qDebug()<<"ModBusTCP断开连接"; |
||||
|
// ui->stageShwoPlain->appendPlainText("与下位机断开连接成功!");
|
||||
|
} |
||||
|
|
||||
|
//===========================================数据发送、接收======================
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::writeSingleFloat 将单个float写入保持性寄存器 |
||||
|
* @param address 写入的保持性寄存器地址 |
||||
|
* @param dataSend 写入的数据 |
||||
|
* @param serverID id |
||||
|
*/ |
||||
|
void MyModbusTcp::writeSingleFloat(int address, float dataSend, int serverID = 1){ |
||||
|
if(modbusDevice->state() != QModbusDevice::ConnectedState){ |
||||
|
// QMessageBox::critical(this, "错误", "MosBusTcp未连接");
|
||||
|
return; |
||||
|
} |
||||
|
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters,address,2); |
||||
|
unsigned int word[2]; |
||||
|
float2Word(dataSend, word); |
||||
|
writeUnit.setValue(0, word[0]); |
||||
|
writeUnit.setValue(1, word[1]); |
||||
|
if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, serverID)) {// ui->spinBox_SerAddress->value()是server address sendWriteRequest是向服务器写数据
|
||||
|
if (!reply->isFinished()) { //reply Returns true when the reply has finished or was aborted.
|
||||
|
//接收响应信息
|
||||
|
connect(reply, &QModbusReply::finished, this, [this, reply]() { |
||||
|
if (reply->error() == QModbusDevice::ProtocolError) { //接收到的响应信息是协议错误
|
||||
|
qDebug() << "写入数据错误:" << reply->errorString(); |
||||
|
} else if (reply->error() != QModbusDevice::NoError) { //接收到的响应消息是其它错误
|
||||
|
qDebug() << "写入数据错误: " << reply->errorString(); |
||||
|
}else { //接收到的消息没有错误 一般没有必要解析响应消息
|
||||
|
const QModbusDataUnit data = reply->result(); |
||||
|
// qDebug() << "消息数据个数:" << data.valueCount() << " :" << data.values();
|
||||
|
} |
||||
|
reply->deleteLater(); |
||||
|
}); |
||||
|
} else { // broadcast replies return immediately
|
||||
|
reply->deleteLater(); |
||||
|
} |
||||
|
} else { |
||||
|
qDebug() << "sendWriteRequest Error: " << reply->errorString(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::writeSingleWord 写入单个word(int) |
||||
|
* @param i 地址 |
||||
|
* @param w 写入的数据 |
||||
|
*/ |
||||
|
void MyModbusTcp::writeSingleWord(int i, int w){ |
||||
|
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters,i,1); |
||||
|
writeUnit.setValue(0, w); |
||||
|
if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, 1)) {// ui->spinBox_SerAddress->value()是server address sendWriteRequest是向服务器写数据
|
||||
|
if (!reply->isFinished()) { //reply Returns true when the reply has finished or was aborted.
|
||||
|
//接收响应信息
|
||||
|
connect(reply, &QModbusReply::finished, this, [this, reply]() { |
||||
|
if (reply->error() == QModbusDevice::ProtocolError) { //接收到的响应信息是协议错误
|
||||
|
qDebug() << "写入数据错误:" << reply->errorString(); |
||||
|
} else if (reply->error() != QModbusDevice::NoError) { //接收到的响应消息是其它错误
|
||||
|
qDebug() << "写入数据错误: " << reply->errorString(); |
||||
|
}else { //接收到的消息没有错误 一般没有必要解析响应消息
|
||||
|
const QModbusDataUnit data = reply->result(); |
||||
|
// qDebug() << "消息数据个数:" << data.valueCount() << " :" << data.values();
|
||||
|
} |
||||
|
reply->deleteLater(); |
||||
|
}); |
||||
|
} else { // broadcast replies return immediately
|
||||
|
reply->deleteLater(); |
||||
|
} |
||||
|
} else { |
||||
|
qDebug() << "sendWriteRequest Error: " << reply->errorString(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::writeMultipleHR 写多个保持性寄存器HR |
||||
|
* @param address 起始地址 |
||||
|
* @param num 数量 |
||||
|
* @param dataSend 写入的数组 |
||||
|
* @param serverID id |
||||
|
*/ |
||||
|
void MyModbusTcp::writeMultipleHR(int address, int num, float *dataSend, int serverID = 1) |
||||
|
{ |
||||
|
if(modbusDevice->state() != QModbusDevice::ConnectedState){ |
||||
|
// QMessageBox::critical(this, "错误", "MosBusTcp未连接");
|
||||
|
return; |
||||
|
} |
||||
|
//发送数据
|
||||
|
qDebug() << "开始发送"; |
||||
|
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, address, num); |
||||
|
unsigned int word[2]; //转换后存放的数组
|
||||
|
for(int i=0;i<6;i++){ |
||||
|
float2Word(dataSend[i], word); |
||||
|
qDebug() << dataSend[i]; |
||||
|
// qDebug() <<*word;
|
||||
|
// qDebug() <<*(word+1);
|
||||
|
writeUnit.setValue(2*i,word[0]); |
||||
|
writeUnit.setValue(2*i+1,word[1]); |
||||
|
} |
||||
|
|
||||
|
if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, serverID)) {// ui->spinBox_SerAddress->value()是server address sendWriteRequest是向服务器写数据
|
||||
|
if (!reply->isFinished()) { //reply Returns true when the reply has finished or was aborted.
|
||||
|
//接收响应信息
|
||||
|
connect(reply, &QModbusReply::finished, this, [this, reply]() { |
||||
|
if (reply->error() == QModbusDevice::ProtocolError) { //接收到的响应信息是协议错误
|
||||
|
qDebug() << "写入数据错误:" << reply->errorString(); |
||||
|
} else if (reply->error() != QModbusDevice::NoError) { //接收到的响应消息是其它错误
|
||||
|
qDebug() << "写入数据错误: " << reply->errorString(); |
||||
|
}else { //接收到的消息没有错误 一般没有必要解析响应消息
|
||||
|
const QModbusDataUnit data = reply->result(); |
||||
|
// qDebug() << "消息数据个数:" << data.valueCount() << " :" << data.values();
|
||||
|
} |
||||
|
reply->deleteLater(); |
||||
|
}); |
||||
|
} else { // broadcast replies return immediately
|
||||
|
reply->deleteLater(); |
||||
|
} |
||||
|
} else { |
||||
|
qDebug() << "sendWriteRequest Error: " ; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::readMultipleHR 读取数据并放到wordRCV数组中 |
||||
|
* @param startAddress 起始地址 |
||||
|
* @param num 数量 |
||||
|
* @param serverID id |
||||
|
*/ |
||||
|
void MyModbusTcp::readMultipleHR(int startAddress, int num, int serverID = 1){ |
||||
|
if(modbusDevice->state() != QModbusDevice::ConnectedState){ |
||||
|
// QMessageBox::critical(this, "错误", "MosBusTcp未连接");
|
||||
|
return; |
||||
|
} |
||||
|
QModbusDataUnit data(QModbusDataUnit::HoldingRegisters, startAddress, num); //地址
|
||||
|
if(auto *reply = modbusDevice->sendReadRequest(data, serverID)){ //发送请求
|
||||
|
if(!reply->isFinished()){ |
||||
|
connect(reply,&QModbusReply::finished, this, &MyModbusTcp::onReadReadyHR_Slot); |
||||
|
} |
||||
|
else{ |
||||
|
delete reply; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::onReadReadyHR_Slot 读取保持性寄存器数据并放到dataRCV数组中 |
||||
|
*/ |
||||
|
void MyModbusTcp:: onReadReadyHR_Slot(){ |
||||
|
if(modbusDevice->state() != QModbusDevice::ConnectedState){ |
||||
|
// QMessageBox::critical(this, "错误", "MosBusTcp未连接");
|
||||
|
return; |
||||
|
} |
||||
|
QModbusReply *reply = qobject_cast<QModbusReply *>(sender()); |
||||
|
if(!reply) return; |
||||
|
if(reply->error() == QModbusDevice::NoError){ |
||||
|
const QModbusDataUnit responseData = reply->result(); //接收的数据
|
||||
|
for(uint i = 0;i<responseData.valueCount();i++){ |
||||
|
wordRCV[i]= responseData.value(i); |
||||
|
} |
||||
|
for(uint i = 0;i<responseData.valueCount();i=i+2){ |
||||
|
float float_data=0; |
||||
|
unsigned long longdata = 0; |
||||
|
longdata = (wordRCV[i]<< 16) + (wordRCV[i+1] << 0); |
||||
|
float_data = *(float*)&longdata; |
||||
|
dataRCV[i/2] = float_data; |
||||
|
} |
||||
|
} |
||||
|
else if (reply->error() == QModbusDevice::ProtocolError) { |
||||
|
qDebug()<<"协议错误"; |
||||
|
qDebug()<<"protocol error:"<<reply->errorString(); |
||||
|
} |
||||
|
else{ |
||||
|
qDebug()<<"回复错误"; |
||||
|
qDebug()<<"error:"<<reply->errorString(); |
||||
|
} |
||||
|
reply->deleteLater(); |
||||
|
} |
||||
|
|
||||
|
//=======================定时获取数据==============================
|
||||
|
/**
|
||||
|
* @brief MyModbusTcp::onTimeReadHR 定时读HR,并保存到dataRCV数组中 |
||||
|
*/ |
||||
|
//void MyModbusTcp::onTimeReadHR()
|
||||
|
//{
|
||||
|
// qDebug()<<"开始持续获取plc数据";
|
||||
|
// timer = new QTimer(this); //启动定时器,100ms
|
||||
|
// connect(timer, SIGNAL(timeout()), this, SLOT(readMultipleHR()));
|
||||
|
// timer->start(1000); // 每隔1000ms
|
||||
|
//}
|
||||
|
|
||||
|
///**
|
||||
|
// * @brief MyModbusTcp::stopOnTimeReadHR 停止获取数据
|
||||
|
// */
|
||||
|
//void MyModbusTcp::stopOnTimeReadHR()
|
||||
|
//{
|
||||
|
// qDebug()<<"停止获取plc数据";
|
||||
|
// timer->stop();
|
||||
|
// timer->deleteLater();
|
||||
|
//}
|
||||
|
|
||||
|
//================================等待时间=========================
|
||||
|
///**
|
||||
|
// * @brief MyModbusTcp::waitTime 等待tms
|
||||
|
// * @param time
|
||||
|
// * @param t
|
||||
|
// */
|
||||
|
//void MyModbusTcp::waitTime(QTime time, int t){
|
||||
|
// time.start(); //设定time为当前时间
|
||||
|
// while(time.elapsed() < t){ //等待时间流逝500ms
|
||||
|
// QCoreApplication::processEvents(); //处理事件
|
||||
|
// }
|
||||
|
//}
|
@ -0,0 +1,111 @@ |
|||||
|
#ifndef MYMODBUSTCP_H |
||||
|
#define MYMODBUSTCP_H |
||||
|
|
||||
|
#include <QModbusTcpClient> |
||||
|
#include <QModbusReply> |
||||
|
#include <QDebug> |
||||
|
#include <QTimer> |
||||
|
#include <QDateTime> |
||||
|
#include <QApplication> |
||||
|
|
||||
|
|
||||
|
class MyModbusTcp : public QObject |
||||
|
{ |
||||
|
public: |
||||
|
MyModbusTcp(); |
||||
|
//声明modbusDevice
|
||||
|
QModbusClient *modbusDevice; |
||||
|
//modbustcp接收的原始数据,以word为单位
|
||||
|
unsigned int wordRCV[40]; |
||||
|
//用于存放读取的数据的数组,float类型
|
||||
|
float dataRCV[30]; |
||||
|
// QTimer *timer = nullptr;
|
||||
|
|
||||
|
/**
|
||||
|
* @brief timeGoBy 等待t毫秒 |
||||
|
* @param time |
||||
|
* @param t |
||||
|
*/ |
||||
|
void timeGoBy(QTime time, int t); |
||||
|
/**
|
||||
|
* @brief connectModbusTcp 连接modbustcp |
||||
|
*/ |
||||
|
void connectModbusTcp(); |
||||
|
|
||||
|
/**
|
||||
|
* @brief disconnectModbusTcp 断开连接 |
||||
|
*/ |
||||
|
void disconnectModbusTcp(); |
||||
|
|
||||
|
/**
|
||||
|
* @brief writeSingleHR 将单个float写入保持性寄存器 |
||||
|
* @param address 写入的保持性寄存器地址 |
||||
|
* @param dataSend 写入的数据 |
||||
|
* @param serverID id |
||||
|
*/ |
||||
|
void writeSingleFloat(int address, float dataSend, int serverID); |
||||
|
/**
|
||||
|
* @brief writeSingleWord 写入单个word(int) |
||||
|
* @param i 地址 |
||||
|
* @param w 写入的数据 |
||||
|
*/ |
||||
|
void writeSingleWord(int i, int w); |
||||
|
/**
|
||||
|
* @brief writeMultipleHR 写多个保持性寄存器HR |
||||
|
* @param address 起始地址 |
||||
|
* @param num 数量 |
||||
|
* @param dataSend 写入的数组 |
||||
|
* @param serverID id |
||||
|
*/ |
||||
|
void writeMultipleHR(int address, int num, float *dataSend, int serverID); |
||||
|
|
||||
|
/**
|
||||
|
* @brief readMultipleHR 读多个保持性寄存器,并保存到dataRCV数组中 |
||||
|
* @param startAddress 起始地址 |
||||
|
* @param num 数量 |
||||
|
* @param serverID id |
||||
|
*/ |
||||
|
void readMultipleHR(int startAddress, int num, int serverID); |
||||
|
|
||||
|
// /**
|
||||
|
// * @brief onTimeReadHR 定时读HR
|
||||
|
// */
|
||||
|
// void onTimeReadHR();
|
||||
|
|
||||
|
// /**
|
||||
|
// * @brief stopOnTimeReadHR 停止定时获取数据
|
||||
|
// */
|
||||
|
// void stopOnTimeReadHR();
|
||||
|
|
||||
|
private: |
||||
|
|
||||
|
/**
|
||||
|
* @brief float2Word 将浮点数f转化为2个8位数据存放在word数组中 |
||||
|
* @param f 待转换的浮点数 |
||||
|
* @param word 转换后的word数组 |
||||
|
*/ |
||||
|
void float2Word(float f, unsigned int *word); |
||||
|
/**
|
||||
|
* @brief word2Float 将2个word数据转化为浮点数 |
||||
|
* @param p 指向word数组的指针 |
||||
|
* @param dataTransformed 转化后的浮点数 |
||||
|
*/ |
||||
|
void word2Float(unsigned int *p, float dataTransformed); |
||||
|
|
||||
|
/**
|
||||
|
* @brief errorOccurred_Slot 错误发生 |
||||
|
*/ |
||||
|
void errorOccurred_Slot(); |
||||
|
|
||||
|
/**
|
||||
|
* @brief stateChanged_SLot 状态改变 |
||||
|
*/ |
||||
|
void stateChanged_SLot(); |
||||
|
|
||||
|
/**
|
||||
|
* @brief onReadReadyHR_Slot HR读取准备就绪 |
||||
|
*/ |
||||
|
void onReadReadyHR_Slot(); |
||||
|
}; |
||||
|
|
||||
|
#endif // MYMODBUSTCP_H
|
Loading…
Reference in new issue