From 0f59612c5dfbf828f1afd9c18d224735dcc09650 Mon Sep 17 00:00:00 2001 From: lipengpeng Date: Sat, 26 Jul 2025 17:09:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=81=E8=A3=85=E4=BA=86modbus=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=8A=A5=E6=96=87=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modbus.pro.user | 2 +- mymodbus.cpp | 54 ------- mymodbus.h | 3 - widget.cpp | 27 ++-- widget.h | 4 + widget.ui | 412 ++++++++++++++++++++++++++---------------------- 6 files changed, 246 insertions(+), 256 deletions(-) diff --git a/modbus.pro.user b/modbus.pro.user index 008fb78..3507302 100644 --- a/modbus.pro.user +++ b/modbus.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/mymodbus.cpp b/mymodbus.cpp index dc0b593..c3a7547 100644 --- a/mymodbus.cpp +++ b/mymodbus.cpp @@ -107,20 +107,6 @@ int MyModbus::ErrorCheck() } } -int MyModbus::ErrorCheck(QByteArray rev) -{ - if ((rev.at(1) & 0x80) == 0x80) - { - // MODBUS异常响应结构:地址 | 功能码+0x80 | 异常码 | CRC - quint8 exCode = rev.at(2); - return exCode; - } - else - { - return 0; - } -} - QVector MyModbus::AnalReadCoil() { quint8 byteCount = static_cast(receive[2]); @@ -158,43 +144,3 @@ QVector MyModbus::AnalReadReg() return registers; } - -QVector MyModbus::AnalReadCoil(QByteArray rev) -{ - quint8 byteCount = static_cast(rev[2]); - QVector coil; - - for (int byteIndex = 0; byteIndex < byteCount; byteIndex++) - { - quint8 byteValue = static_cast(rev[3 + byteIndex]); - - // 解析每个字节的8个位 - for (int bitIndex = 0; bitIndex < 8; bitIndex++) - { - int coilIndex = byteIndex * 8 + bitIndex; - if (coilIndex < length) - { - bool state = byteValue & (1 << bitIndex); - coil.append(state); - } - } - } - return coil; -} - -QVector MyModbus::AnalReadReg(QByteArray rev) -{ - int byteCount = rev.at(2); - QByteArray data = rev.mid(3, byteCount); - - QVector registers; - for (int i = 0; i < data.size(); i += 2) - { - quint16 value = (static_cast(data[i]) << 8) | static_cast(data[i+1]); - registers.append(value); - } - - return registers; -} - - diff --git a/mymodbus.h b/mymodbus.h index cb7aeef..0f73496 100644 --- a/mymodbus.h +++ b/mymodbus.h @@ -25,11 +25,8 @@ public: QByteArray SendCommand(); QByteArray Receive(const QByteArray &revMessage); int ErrorCheck(); - int ErrorCheck(QByteArray rev); QVector AnalReadCoil(); QVector AnalReadReg(); - QVector AnalReadCoil(QByteArray rev); - QVector AnalReadReg(QByteArray rev); }; #endif // MYMODBUS_H diff --git a/widget.cpp b/widget.cpp index 44a824d..246d093 100644 --- a/widget.cpp +++ b/widget.cpp @@ -20,8 +20,10 @@ Widget::Widget(QWidget *parent) : ui->setupUi(this); serialPort = new QSerialPort(this); modbus = new MyModbus(); + recvTimer = new QTimer(this); - connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_SerialData_ReadyToRead); + connect(serialPort, &QSerialPort::readyRead, this, &Widget::onReadyRead); + connect(recvTimer, &QTimer::timeout, this, &Widget::on_SerialData_ReadyToRead); QObject::connect(&timer, &QTimer::timeout, [&]{ if (comCount < 3) { @@ -155,11 +157,10 @@ void Widget::on_pushWrite_clicked() ui->pushWrite->setEnabled(0); comCount = 0; - Sleep(200); + Sleep(100); timer.isActive(); timer.start(1000); // 1 s 后触发超时 - qDebug() << "SenOk" <pushWrite->setEnabled(0); comCount = 0; - Sleep(200); + Sleep(100); timer.isActive(); timer.start(1000); // 1 s 后触发超时 @@ -219,7 +220,9 @@ void Widget::on_pushWrite_clicked() //处理回复报文 void Widget::on_SerialData_ReadyToRead() { - QByteArray revMessage = modbus->Receive(serialPort->readAll()); + QByteArray revMessage = recvBuffer; + recvBuffer.clear(); + revMessage = modbus->Receive(revMessage); if (!revMessage.isEmpty()) { ui->btn_read->setEnabled(1); @@ -235,7 +238,7 @@ void Widget::on_SerialData_ReadyToRead() ui->textEdit_2->append("接收报文"+hexData); qDebug() << "接收成功"; - int exCode = modbus->ErrorCheck(revMessage); + int exCode = modbus->ErrorCheck(); if (exCode) { QString errorMsg; @@ -261,7 +264,7 @@ void Widget::on_SerialData_ReadyToRead() //解析读线圈的返回报文 case 0: { - QVector coil = modbus->AnalReadCoil(revMessage); + QVector coil = modbus->AnalReadCoil(); ui->textEdit->append("线圈状态:"); for (int i = 0; i < coil.size(); i++) @@ -275,7 +278,7 @@ void Widget::on_SerialData_ReadyToRead() //解析读寄存器的返回报文 case 1: { - QVector registers = modbus->AnalReadReg(revMessage); + QVector registers = modbus->AnalReadReg(); ui->textEdit->append("寄存器的值:"); for (int i = 0; i < registers.size(); i++) @@ -322,7 +325,7 @@ void Widget::on_btn_read_clicked() ui->pushWrite->setEnabled(0); comCount = 0; - Sleep(200); + Sleep(100); timer.isActive(); timer.start(1000); // 1 s 后触发超时 } @@ -383,3 +386,9 @@ void Widget::on_pushButton_3_clicked() { ui->textEdit_2->clear(); } + +void Widget::onReadyRead() +{ + recvBuffer.append(serialPort->readAll()); + recvTimer->start(50); // 50ms 内无新数据即认为接收完成 +} diff --git a/widget.h b/widget.h index a8ffe3f..765a82b 100644 --- a/widget.h +++ b/widget.h @@ -33,12 +33,16 @@ private slots: void on_pushButton_3_clicked(); + void onReadyRead(); + private: Ui::Widget *ui; QSerialPort *serialPort; MyModbus *modbus; QTimer timer; int comCount; + QByteArray recvBuffer; + QTimer *recvTimer; }; #endif // WIDGET_H diff --git a/widget.ui b/widget.ui index 1c5cd1a..0750755 100644 --- a/widget.ui +++ b/widget.ui @@ -26,7 +26,7 @@ - 350 + 340 470 93 28 @@ -40,16 +40,19 @@ 40 - 250 + 280 251 - 211 + 191 + + true + - 110 + 200 470 93 28 @@ -59,12 +62,220 @@ - + + + + 340 + 330 + 311 + 101 + + + + 写线圈时,使用1、0代表线圈的开关状态, +从左到右依次输入每个线圈的开关; +写寄存器时要写入所有寄存器的16进制数值, +相邻寄存器的值之间用英文","分离。 + + + + + + 40 + 10 + 72 + 15 + + + + 串口配置 + + + + + + 40 + 100 + 72 + 15 + + + + 从站配置 + + + 40 - 115 - 672 + 150 + 72 + 15 + + + + 状态通知 + + + + + + 42 + 32 + 406 + 58 + + + + + + + 串口 + + + + + + + + + + 波特率 + + + + + + + + 1200 + + + + + 2400 + + + + + 4800 + + + + + 9600 + + + + + 19200 + + + + + 38400 + + + + + + + + 数据位 + + + + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + NONE + + + + + + + + 校验位 + + + + + + + + 无校验(N) + + + + + 奇校验(O) + + + + + 偶校验(E) + + + + + + + + 停止位 + + + + + + + + 1 + + + + + 2 + + + + + + + + 连接 + + + + + + + + + 41 + 116 + 687 23 @@ -186,198 +397,21 @@ - - - - 340 - 330 - 311 - 101 - - - - 写线圈时,使用1、0代表线圈的开关状态, -从左到右依次输入每个线圈的开关; -写寄存器时要写入所有寄存器的16进制数值, -相邻寄存器的值之间用英文","分离。 - - - - - - 40 - 30 - 378 - 62 - - - - - - - - - 串口 - - - - - - - - - - 波特率 - - - - - - - - 1200 - - - - - 2400 - - - - - 4800 - - - - - 9600 - - - - - 19200 - - - - - 38400 - - - - - - - - 数据位 - - - - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - NONE - - - - - - - - - - - - 校验位 - - - - - - - - 无校验(N) - - - - - 奇校验(O) - - - - - 偶校验(E) - - - - - - - - 停止位 - - - - - - - - 1 - - - - - 2 - - - - - - - - 连接 - - - - - - - - 40 - 150 - 671 + 41 + 164 + 691 91 - + - +