Browse Source

封装了串口配置相关的代码

master
鹏鹏 李 1 week ago
parent
commit
86611b2a14
7 changed files with 569 additions and 163 deletions
  1. +4
    -2
      modbus.pro
  2. +1
    -1
      modbus.pro.user
  3. +9
    -8
      mymodbus.h
  4. +268
    -0
      serialcommunicator.cpp
  5. +178
    -0
      serialcommunicator.h
  6. +100
    -143
      widget.cpp
  7. +9
    -9
      widget.h

+ 4
- 2
modbus.pro View File

@@ -16,10 +16,12 @@ TEMPLATE = app
SOURCES += main.cpp\
widget.cpp \
mymodbus.cpp \
communicationhistory.cpp
communicationhistory.cpp \
serialcommunicator.cpp

HEADERS += widget.h \
mymodbus.h \
communicationhistory.h
communicationhistory.h \
serialcommunicator.h

FORMS += widget.ui

+ 1
- 1
modbus.pro.user View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.0.3, 2025-07-28T16:03:38. -->
<!-- Written by QtCreator 4.0.3, 2025-07-28T19:27:23. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>


+ 9
- 8
mymodbus.h View File

@@ -1,11 +1,3 @@
#ifndef MYMODBUS_H
#define MYMODBUS_H

#include <QByteArray>
#include <QVector>
#include <QString>
#include <QtGlobal>

/******************************************************************************
* Copyright (C) 2025-.
*
@@ -18,6 +10,15 @@
*
******************************************************************************/

#ifndef MYMODBUS_H
#define MYMODBUS_H

#include <QByteArray>
#include <QVector>
#include <QString>
#include <QtGlobal>


/**
* @class MyModbus
* @brief Modbus RTU协议封装类


+ 268
- 0
serialcommunicator.cpp View File

@@ -0,0 +1,268 @@
/*******************************
* Copyright (C) 2023-, XINJE Electronic Co., Ltd.
*
* File Name: serialcommunicator.cpp
* Description: 串口通信管理类实现文件
* Others:
* Version: 1.0
* Author: lipengpeng
* Date: 2025-7-23
*******************************/

#include "serialcommunicator.h"

/**
* @brief 构造函数
* @param parent 父对象指针
*
* @details 初始化串口通信组件,包括:
* 1. 创建串口对象
* 2. 创建接收和重发定时器
* 3. 设置默认超时参数
* 4. 连接信号槽
*/
SerialCommunicator::SerialCommunicator(QObject *parent) : QObject(parent)
, serialPort(new QSerialPort(this))
, recvTimer(new QTimer(this))
, resendTimer(new QTimer(this))
, comCount(0)
, maxRetry(3)
, recvTimeout(50)
, resendTimeout(1000)
{
// 配置定时器(单次触发)
recvTimer->setSingleShot(true);
resendTimer->setSingleShot(true);

// 连接信号槽
connect(serialPort, &QSerialPort::readyRead, this, &SerialCommunicator::onReadyRead);
connect(recvTimer, &QTimer::timeout, this, &SerialCommunicator::onRecvTimeout);
connect(resendTimer, &QTimer::timeout, this, &SerialCommunicator::onResendTimeout);
}

/**
* @brief 析构函数
* @note 确保串口关闭并释放资源
*/
SerialCommunicator::~SerialCommunicator()
{
close();
}

/**
* @brief 设置串口参数
* @param portName 串口号(如"COM1")
* @param baudRate 波特率(如9600)
* @param dataBits 数据位
* @param parity 校验位
* @param stopBits 停止位
*
* @note 此方法应在打开串口前调用,设置值将在下次open()时生效
*/
void SerialCommunicator::setPortParams(const QString &portName, qint32 baudRate,
QSerialPort::DataBits dataBits,
QSerialPort::Parity parity,
QSerialPort::StopBits stopBits)
{
this->portName = portName;
this->baudRate = baudRate;
this->dataBits = dataBits;
this->parity = parity;
this->stopBits = stopBits;
}

/**
* @brief 打开串口
* @return true-打开成功, false-打开失败
*
* @details 执行流程:
* 1. 关闭已打开的串口(如果存在)
* 2. 配置串口参数(波特率、数据位等)
* 3. 尝试打开串口
* 4. 发送状态变化信号
*/
bool SerialCommunicator::open()
{
// 关闭已打开的串口(如果存在)
if (serialPort->isOpen())
{
serialPort->close();
}

// 配置串口参数
serialPort->setPortName(portName);
if (!serialPort->setBaudRate(baudRate))
{
emit statusChanged("波特率设置失败");
return false;
}
if (!serialPort->setDataBits(dataBits))
{
emit statusChanged("数据位设置失败");
return false;
}
if (!serialPort->setParity(parity))
{
emit statusChanged("校验位设置失败");
return false;
}
if (!serialPort->setStopBits(stopBits))
{
emit statusChanged("停止位设置失败");
return false;
}
serialPort->setFlowControl(QSerialPort::NoFlowControl); // 无流控制

// 打开串口
if (serialPort->open(QIODevice::ReadWrite))
{
emit statusChanged("串口连接成功");
return true;
}
else
{
emit statusChanged("串口连接失败,请检查参数");
return false;
}
}

/**
* @brief 关闭串口
*
* @details 执行流程:
* 1. 检查串口是否打开
* 2. 关闭串口
* 3. 发送状态变化信号
*/
void SerialCommunicator::close()
{
if (serialPort->isOpen())
{
serialPort->close();
emit statusChanged("串口断开");
}
}

/**
* @brief 发送数据并启动超时重发机制
* @param data 待发送的数据
*
* @details 执行流程:
* 1. 检查串口是否打开
* 2. 保存待发送数据(用于重发)
* 3. 重置重发计数器
* 4. 发送数据
* 5. 启动重发超时定时器
*/
void SerialCommunicator::sendData(const QByteArray &data)
{
if (!serialPort->isOpen())
{
emit statusChanged("串口未打开,无法发送数据");
return;
}
// 保存待重发数据,初始化计数器,启动重发定时器
currentData = data;
comCount = 0;
serialPort->write(data); // 发送数据
emit statusChanged("发送报文:" + data.toHex().toUpper());
resendTimer->start(resendTimeout); // 启动超时计时
}

/**
* @brief 设置最大重发次数
* @param count 最大重发次数
*/
void SerialCommunicator::setMaxRetry(int count)
{
maxRetry = count;
}

/**
* @brief 设置接收完成超时时间
* @param ms 超时时间(毫秒)
*
* @note 当串口持续ms毫秒无新数据时,认为接收完成
*/
void SerialCommunicator::setRecvTimeout(int ms)
{
recvTimeout = ms;
}

/**
* @brief 设置重发间隔时间
* @param ms 重发间隔(毫秒)
*/
void SerialCommunicator::setResendTimeout(int ms)
{
resendTimeout = ms;
}

/**
* @brief 检查串口是否打开
* @return true-已打开, false-已关闭
*/
bool SerialCommunicator::isOpen() const
{
return serialPort->isOpen();
}

// ====================== 私有槽函数 ====================== //

/**
* @brief 串口数据到达处理
*
* @details 执行流程:
* 1. 读取所有可用数据到接收缓冲区
* 2. 重启接收超时定时器
* 3. 定时器超时后将触发onRecvTimeout
*/
void SerialCommunicator::onReadyRead()
{
// 读取数据到缓冲区
recvBuffer.append(serialPort->readAll());
//重置接收超时定时器
recvTimer->start(recvTimeout);
}

/**
* @brief 接收完成超时处理
*
* @details 执行流程:
* 1. 发送dataReceived信号包含完整数据
* 2. 清空接收缓冲区
* 3. 停止重发定时器(表示已收到响应)
*/
void SerialCommunicator::onRecvTimeout()
{
// 接收完成,发送完整数据信号,停止重发定时器
emit dataReceived(recvBuffer);
recvBuffer.clear();
resendTimer->stop();
}

/**
* @brief 重发超时处理
*
* @details 执行流程:
* 1. 检查是否达到最大重发次数
* 2. 未达到则重发数据并更新计数器
* 3. 达到最大次数则触发超时信号
*/
void SerialCommunicator::onResendTimeout()
{
if (comCount < maxRetry)
{
// 重发数据,更新计数器
serialPort->write(currentData);
comCount++;
emit statusChanged(QString("通信超时,重新发送中(%1/%2)").arg(comCount).arg(maxRetry));
resendTimer->start(resendTimeout); // 继续计时
}
else
{
// 达到最大重发次数,触发超时信号
resendTimer->stop();
emit timeoutOccurred();
}
}

+ 178
- 0
serialcommunicator.h View File

@@ -0,0 +1,178 @@
/*******************************
* Copyright (C) 2025-.
*
* File Name: serialcommunicator.h
* Description: 串口通信管理类,封装串口操作、数据收发和超时处理
* Others:
* Version: 1.0
* Author: lipengpeng
* Date: 2025-7-23
*******************************/
#ifndef SERIALCOMMUNICATOR_H
#define SERIALCOMMUNICATOR_H

#include <QObject>
#include <QSerialPort>
#include <QTimer>
#include <QByteArray>

/**
* @brief 串口通信管理类
* @class SerialCommunicator
*
* @details 此类封装了串口通信的核心功能,包括:
* 1. 串口参数配置与开关控制
* 2. 数据发送与自动重发机制
* 3. 数据接收与完整性判断
* 4. 超时处理与状态通知
*
* @note 使用流程:
* 1. 设置串口参数(setPortParams)
* 2. 打开串口(open)
* 3. 发送数据(sendData)
* 4. 接收数据(通过dataReceived信号)
* 5. 关闭串口(close)
*/
class SerialCommunicator : public QObject
{
Q_OBJECT
public:
/**
* @brief 构造函数
* @param parent 父对象指针
*/
explicit SerialCommunicator(QObject *parent = nullptr);

/**
* @brief 析构函数
* @note 自动关闭串口并释放资源
*/
~SerialCommunicator();

// ====================== 串口配置 ====================== //

/**
* @brief 设置串口参数
* @param portName 串口号(如"COM1"或"/dev/ttyS0")
* @param baudRate 波特率(如9600, 115200)
* @param dataBits 数据位(通常为QSerialPort::Data8)
* @param parity 校验位(无校验/奇校验/偶校验)
* @param stopBits 停止位(通常为QSerialPort::OneStop)
* @note 此方法应在打开串口前调用
*/
void setPortParams(const QString &portName, qint32 baudRate,
QSerialPort::DataBits dataBits,
QSerialPort::Parity parity,
QSerialPort::StopBits stopBits);

/**
* @brief 打开串口
* @return true-打开成功, false-打开失败
* @note 成功打开后会发出statusChanged信号
*/
bool open();

/**
* @brief 关闭串口
* @note 关闭后会发出statusChanged信号
*/
void close();

// ====================== 数据操作 ====================== //

/**
* @brief 发送数据并启动超时重发机制
* @param data 待发送的数据
* @note 数据发送后启动重发定时器,如达到最大重发次数仍未收到响应,
* 将发出timeoutOccurred信号
*/
void sendData(const QByteArray &data);

// ====================== 超时配置 ====================== //

/**
* @brief 设置最大重发次数
* @param count 重发次数(默认3次)
*/
void setMaxRetry(int count);

/**
* @brief 设置接收完成超时时间
* @param ms 超时时间(毫秒,默认50ms)
* @note 当串口持续ms毫秒无新数据时,认为接收完成
*/
void setRecvTimeout(int ms);

/**
* @brief 设置重发间隔时间
* @param ms 重发间隔(毫秒,默认1000ms)
*/
void setResendTimeout(int ms);

// ====================== 状态查询 ====================== //

/**
* @brief 检查串口是否打开
* @return true-已打开, false-已关闭
*/
bool isOpen() const;

signals:
/**
* @brief 接收到完整数据信号
* @param data 接收到的完整数据包
*/
void dataReceived(const QByteArray &data);

/**
* @brief 状态变化信号
* @param status 状态描述文本
* @note 可能的状态: "已连接", "已断开", "接收超时"等
*/
void statusChanged(const QString &status);

/**
* @brief 通信超时信号
* @note 当达到最大重发次数仍未收到响应时触发
*/
void timeoutOccurred();

private slots:
/**
* @brief 串口数据到达处理
* @note 当串口有数据可读时触发,数据存入缓冲区并启动接收超时定时器
*/
void onReadyRead();

/**
* @brief 接收完成超时处理
* @note 当recvTimer超时,认为数据接收完成,发出dataReceived信号
*/
void onRecvTimeout();

/**
* @brief 重发超时处理
* @note 当resendTimer超时,检查重发次数并决定是否重发数据
*/
void onResendTimeout();

private:
QSerialPort *serialPort; // 串口对象
QTimer *recvTimer; // 接收完成判断定时器
QTimer *resendTimer; // 超时重发定时器
QByteArray recvBuffer; // 接收缓冲区
QByteArray currentData; // 当前待重发数据
int comCount; // 重发计数器
int maxRetry; // 最大重发次数
int recvTimeout; // 接收超时时间(ms)
int resendTimeout; // 重发间隔(ms)

// 串口参数
QString portName;
qint32 baudRate;
QSerialPort::DataBits dataBits;
QSerialPort::Parity parity;
QSerialPort::StopBits stopBits;
};

#endif // SERIALCOMMUNICATOR_H

+ 100
- 143
widget.cpp View File

@@ -8,36 +8,24 @@
#include <QVector>
#include <QMessageBox>
#include <synchapi.h>
#include "mymodbus.h"
#include "communicationhistory.h"

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
serialPort = new QSerialPort(this);
modbus = new MyModbus();
recvTimer = new QTimer(this);
ui->setupUi(this);
serialComm = new SerialCommunicator(this); // 初始化串口通信类

connect(serialPort, &QSerialPort::readyRead, this, &Widget::onReadyRead);
connect(recvTimer, &QTimer::timeout, this, &Widget::on_SerialData_ReadyToRead);
QObject::connect(&timer, &QTimer::timeout, [this]{
if (comCount < 3)
{
ui->textEdit_2->append("通信超时,重新发送中");
// 配置串口参数
serialComm->setMaxRetry(3); // 最大重发3次
serialComm->setRecvTimeout(50); // 接收超时50ms
serialComm->setResendTimeout(1000); // 重发间隔1s

serialPort->write(modbus->SendCommand());
comCount ++;
}
else
{
QMessageBox::warning(this, "提示", "等待响应超时,请检查设备状态。");
ui->btn_read->setEnabled(1);
ui->pushWrite->setEnabled(1);
timer.stop();
}
});
// 连接信号槽(串口->界面)
connect(serialComm, &SerialCommunicator::dataReceived, this, &Widget::onSerialDataReceived);
connect(serialComm, &SerialCommunicator::statusChanged, this, &Widget::onSerialStatusChanged);
connect(serialComm, &SerialCommunicator::timeoutOccurred, this, &Widget::onSerialTimeout);

ui->comboBox_baudRate->setCurrentIndex(3);
ui->comboBox_dataBit->setCurrentIndex(3);
@@ -56,6 +44,7 @@ Widget::Widget(QWidget *parent) :
Widget::~Widget()
{
delete modbus;
delete serialComm;
delete ui;
}

@@ -64,47 +53,40 @@ void Widget::on_btnConnect_clicked()
{
if (ui->btnConnect->text() == "连接")
{
//配置串口号
serialPort->setPortName(ui->comboBox_serialNum->currentText());
//配置波特率
serialPort->setBaudRate(ui->comboBox_baudRate->currentText().toInt());
//配置数据位
serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_dataBit->currentText().toInt()));
//配置校验位
// 获取界面配置的串口参数
QString portName = ui->comboBox_serialNum->currentText();
qint32 baudRate = ui->comboBox_baudRate->currentText().toInt();
QSerialPort::DataBits dataBits = QSerialPort::DataBits(ui->comboBox_dataBit->currentText().toInt());
QSerialPort::Parity parity;
switch (ui->comboBox_xiaoyan->currentIndex())
{
case 0:
serialPort->setParity(QSerialPort::NoParity);
break;
case 1:
serialPort->setParity(QSerialPort::OddParity);
break;
case 2:
serialPort->setParity(QSerialPort::EvenParity);
case 0: parity = QSerialPort::NoParity; break;
case 1: parity = QSerialPort::OddParity; break;
case 2: parity = QSerialPort::EvenParity; break;
default: parity = QSerialPort::NoParity;
}
//配置停止位
serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_stopBit->currentText().toInt()));
//打开串口
if (serialPort->open(QIODevice::ReadWrite))
QSerialPort::StopBits stopBits = QSerialPort::StopBits(ui->comboBox_stopBit->currentText().toInt());

// 配置并打开串口
serialComm->setPortParams(portName, baudRate, dataBits, parity, stopBits);
if (serialComm->open())
{
ui->textEdit_2->append("串口连接成功");
ui->btnConnect->setText("断开");
ui->btn_read->setEnabled(1);
ui->pushWrite->setEnabled(1);
ui->btn_read->setEnabled(true);
ui->pushWrite->setEnabled(true);
}
else
{
QMessageBox::warning(this, "提示", "串口连接失败,请检查串口参数配置");
QMessageBox::warning(this, "提示", "串口连接失败");
}
}
else
{
serialPort->close();
ui->btn_read->setEnabled(0);
ui->pushWrite->setEnabled(0);
qDebug() << "Serial close";
// 断开串口
serialComm->close();
ui->btnConnect->setText("连接");
ui->textEdit_2->append("串口断开");
ui->btn_read->setEnabled(false);
ui->pushWrite->setEnabled(false);
}

}
@@ -149,14 +131,10 @@ void Widget::on_pushWrite_clicked()
modbus->Set(stationAddress,functionCode,stratAddress,length);
modbus->WriteCoil(coils);

ui->textEdit_2->append("发送报文"+modbus->SendCommand().toHex().toUpper());
serialPort->write(modbus->SendCommand());
serialComm->sendData(modbus->SendCommand());
ui->btn_read->setEnabled(0);
ui->pushWrite->setEnabled(0);

comCount = 0;
timer.start(1000); // 1 s 后触发超时

break;
}

@@ -196,14 +174,10 @@ void Widget::on_pushWrite_clicked()
modbus->Set(stationAddress,functionCode,stratAddress,length);
modbus->WriteRegister(values); //要发送的报文

ui->textEdit_2->append("发送报文"+modbus->SendCommand().toHex().toUpper());
serialPort->write(modbus->SendCommand());
serialComm->sendData(modbus->SendCommand());
ui->btn_read->setEnabled(0);
ui->pushWrite->setEnabled(0);

comCount = 0;
timer.start(1000); // 1 s 后触发超时

break;
}
default:
@@ -215,80 +189,6 @@ void Widget::on_pushWrite_clicked()
}
}

//处理回复报文
void Widget::on_SerialData_ReadyToRead()
{
QByteArray revMessage = recvBuffer;
recvBuffer.clear();
revMessage = modbus->Receive(revMessage);
if (!revMessage.isEmpty())
{
ui->btn_read->setEnabled(1);
ui->pushWrite->setEnabled(1);
timer.stop();
}
else
{
return;
}
QString hexData = revMessage.toHex().toUpper();
ui->textEdit_2->append("接收报文"+hexData);

int exCode = modbus->ErrorCheck();
if (exCode)
{
QString errorMsg;
switch (exCode)
{
case 0x01: errorMsg = "非法功能码"; break;
case 0x02: errorMsg = "非法数据地址"; break;
case 0x03: errorMsg = "非法数据值"; break;
case 0x04: errorMsg = "从站设备故障"; break;
default: errorMsg = "未知异常"; break;
}

QMessageBox::warning(this, "异常响应",
QString("异常\n错误码: 0x%1 (%2)")
.arg(QString::number(exCode, 16).toUpper().rightJustified(2, '0'))
.arg(errorMsg));

return;
}

switch (ui->comboBox_gongnengma->currentIndex())
{
//解析读线圈的返回报文
case 0:
{
QVector<bool> coil = modbus->AnalReadCoil();

ui->textEdit->append("线圈状态:");
for (int i = 0; i < coil.size(); i++)
{
bool state = coil.at(i);
ui->textEdit->append("线圈"+QString::number(i+1)+":"+QString::number(state));
}

break;
}
//解析读寄存器的返回报文
case 1:
{
QVector<quint16> registers = modbus->AnalReadReg();

ui->textEdit->append("寄存器的值:");
for (int i = 0; i < registers.size(); i++)
{
ui->textEdit->append("寄存器"+QString::number(i+1)+":"+QString::number(registers.at(i)));
}

break;

}

}
}

//发送读线圈和寄存器报文
void Widget::on_btn_read_clicked()
{
@@ -315,13 +215,10 @@ void Widget::on_btn_read_clicked()
modbus->Set(stationAddress,functionCode,stratAddress,length);
modbus->ReadCoilAndReg();

serialPort->write(modbus->SendCommand()); //发送报文
ui->textEdit_2->append("发送报文"+modbus->SendCommand().toHex().toUpper());
serialComm->sendData(modbus->SendCommand());
ui->btn_read->setEnabled(0);
ui->pushWrite->setEnabled(0);

comCount = 0;
timer.start(1000); // 1 s 后触发超时
}

void Widget::on_btn_SaveDate_clicked()
@@ -339,13 +236,73 @@ void Widget::on_btn_ClearDate_clicked()
ui->textEdit_2->clear();
}

void Widget::onReadyRead()
void Widget::on_btn_ClearRead_clicked()
{
recvBuffer.append(serialPort->readAll());
recvTimer->start(50); // 50ms 内无新数据即认为接收完成
ui->textEdit->clear();
}

void Widget::on_btn_ClearRead_clicked()
void Widget::onSerialDataReceived(const QByteArray &data)
{
ui->textEdit->clear();
QByteArray revMessage = modbus->Receive(data); // 交给Modbus解析
if (revMessage.isEmpty()) return;

// 启用操作按钮
ui->btn_read->setEnabled(true);
ui->pushWrite->setEnabled(true);
ui->textEdit_2->append("接收报文:" + revMessage.toHex().toUpper());

// 检查Modbus错误码
int exCode = modbus->ErrorCheck();
if (exCode)
{
QString errorMsg;
switch (exCode) {
case 0x01: errorMsg = "非法功能码"; break;
case 0x02: errorMsg = "非法数据地址"; break;
case 0x03: errorMsg = "非法数据值"; break;
case 0x04: errorMsg = "从站设备故障"; break;
default: errorMsg = "未知异常"; break;
}
QMessageBox::warning(this, "异常响应",
QString("错误码: 0x%1(%2)").arg(QString::number(exCode, 16).toUpper(), errorMsg));
return;
}

// 解析并显示数据(根据功能码)
switch (ui->comboBox_gongnengma->currentIndex())
{
case 0:
{ // 读线圈
QVector<bool> coils = modbus->AnalReadCoil();
ui->textEdit->append("线圈状态:");
for (int i = 0; i < coils.size(); i++)
{
ui->textEdit->append(QString("线圈%1: %2").arg(i+1).arg(coils[i] ? "1" : "0"));
}
break;
}
case 1:
{ // 读寄存器
QVector<quint16> regs = modbus->AnalReadReg();
ui->textEdit->append("寄存器值:");
for (int i = 0; i < regs.size(); i++)
{
ui->textEdit->append(QString("寄存器%1: %2").arg(i+1).arg(regs[i]));
}
break;
}
}
}

void Widget::onSerialStatusChanged(const QString &status)
{
ui->textEdit_2->append(status); // 显示状态信息(如连接成功、超时重发等)
}


void Widget::onSerialTimeout()
{
QMessageBox::warning(this, "提示", "等待响应超时,请检查设备");
ui->btn_read->setEnabled(true);
ui->pushWrite->setEnabled(true);
}

+ 9
- 9
widget.h View File

@@ -5,6 +5,8 @@
#include <QWidget>
#include <QTimer>
#include "mymodbus.h"
#include "communicationhistory.h"
#include "serialcommunicator.h"

namespace Ui {
class Widget;
@@ -23,8 +25,6 @@ private slots:

void on_pushWrite_clicked();

void on_SerialData_ReadyToRead();

void on_btn_read_clicked();

void on_btn_SaveDate_clicked();
@@ -33,18 +33,18 @@ private slots:

void on_btn_ClearDate_clicked();

void onReadyRead();

void on_btn_ClearRead_clicked();

void onSerialDataReceived(const QByteArray &data);

void onSerialStatusChanged(const QString &status);

void onSerialTimeout();

private:
Ui::Widget *ui;
QSerialPort *serialPort;
SerialCommunicator *serialComm;
MyModbus *modbus;
QTimer timer;
int comCount;
QByteArray recvBuffer;
QTimer *recvTimer;
};

#endif // WIDGET_H

Loading…
Cancel
Save