原使用在QT5.12版本,用modbus RTU 会出现界面卡死的现象,使用多线程信号传递也有问题,现在换新的5.15版本正常如图:
采用聚英rs232的4入4出设备。
按钮全开写入全部线圈和输入1
//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_5_clicked();//连接
void onModbusStateChanged();//状态
void readModbusINUnit(QModbusDataUnit::RegisterType type, int startAddr, int numbers, int serverID);//DiscreteInputs读取
void readModbusOUTUnit(QModbusDataUnit::RegisterType type, int startAddr, int numbers, int serverID, bool *isOK);//Coils读取
void Readinput();//输入连接读取
void Readout();//输出连接读取
void textbrowser(QString value);//文本浏览框
//void showAbout();//关于
void openApp();//托盘打开
void quitApp() ;//托盘退出
void pbMin();//最小化
void onActivated(QSystemTrayIcon::ActivationReason reason);
void initConnect();
void on_pushButton_6_clicked();//断开
void on_alloffbtn_clicked();//全关
void on_allonbtn_clicked();//全开
void Write(int val,int val2,QString val3);//线圈写入
void RefreshTaskbarIcon();//任务栏图标刷新一遍
void on_outbtn_1_clicked();//开关1
void on_outbtn_2_clicked();//开关2
void on_outbtn_3_clicked();//开关3
void on_outbtn_4_clicked();//开关4
//void recvMsg();//接收函数
void on_IPlineEdit_editingFinished();
void on_PortlineEdit_editingFinished();
void Delay(int time);//延时
void closeEvent ( QCloseEvent * e );
void on_comboBox_activated(const QString &arg1);
void on_comboBox_2_activated(const QString &arg1);
private:
Ui::MainWindow *ui;
QModbusRtuSerialMaster* modbusDevice;
QTimer *timer;
QTimer* timer_2;
QMenu*trayIconMenu;//系统托盘菜单
QSystemTrayIcon*trayIcon;//系统托盘ICO
QAction*aboutAction ;//建立modbus对象
QAction*openAction;//建立modbus对象
QAction* quitAction;//建立modbus对象
QSettings* configIni;//建立ini文件对象
QSettings* name;//建立name ini文件对象
QUdpSocket *udpsocket;//建立udp对象
QIntValidator* IntValidator;//校验
QSerialPort* serial;
};
#endif // MAINWINDOW_H
//por
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
QT += serialbus serialport widgets core
requires(qtConfig(combobox))
#QMAKE_CXXFLAGS += /utf-8
QT += concurrent
TARGET = DODI04
RC_ICONS = favicon.ico
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES +=
main.cpp
mainwindow.cpp
HEADERS +=
mainwindow.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
RESOURCES +=
titl.qrc
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
QString strAppPath = QDir::toNativeSeparators(QCoreApplication::applicationDirPath());//路径获取
aboutAction = new QAction("关于", this); // 托盘空件创建
this->aboutAction->setIcon(QIcon::fromTheme("help-about"));//托盘添加关于
openAction = new QAction("打开", this);
this->openAction->setIcon(QIcon::fromTheme("media-record"));//托盘添加打开按钮
quitAction = new QAction(this);//托盘添加退出按钮
this->quitAction->setText("退出");
this->quitAction->setIcon(QIcon::fromTheme("application-exit"));// 从系统主题获取图标
trayIconMenu = new QMenu(this); // 托盘菜单
this->trayIconMenu->addAction(aboutAction);//托盘添加关于按钮
//this->trayIconMenu->addSeparator();
this->trayIconMenu->addAction(openAction);//托盘添加打开按钮
this->trayIconMenu->addAction(quitAction);//托盘添加退出按钮
trayIcon = new QSystemTrayIcon(this); // 托盘图标
this->trayIcon->setContextMenu(trayIconMenu);
this->trayIcon->setIcon(QIcon(":/favicon.ico"));
this->trayIcon->setToolTip("DODI0404D");
this->trayIcon->show(); // 托盘空件
this->initConnect();//初始化托盘
ui->setupUi(this);
ui->textBrowser->document ()->setMaximumBlockCount (50);//textbrowser 行数限制
this->setWindowIcon(QIcon(":/favicon.ico"));//标题LOGO
this->setWindowTitle("DODI04");
this->setFixedSize(410,425);
ui->comboBox_2->addItem("9600");
ui->comboBox_2->addItem("19200");
ui->comboBox_2->addItem("115200");
ui->statusbar->setSizeGripEnabled(false);//去掉状态栏右下角的三角
QLabel *permanent=new QLabel(this);//状态栏版本信息
//permanent->setFrameStyle(QFrame::Box|QFrame::Sunken);//box 样式
permanent->setText(tr("版本V1.0"));
permanent->setStyleSheet(QString("QStatusBar::item{border: 0px}")); // 不显示label的边框
//permanent->setOpenExternalLinks(true);//设置可以打开网站链接
ui->statusbar->addPermanentWidget(permanent);//显示永久信息
serial = new QSerialPort(this);
modbusDevice = new QModbusRtuSerialMaster(this);
connect(modbusDevice, &QModbusClient::errorOccurred, [this](QModbusDevice::Error) {//连接modbus error
ui->statusbar->showMessage(modbusDevice->errorString());
if (modbusDevice->errorString() != NULL){
// on_pushButton_6_clicked();
// this->Delay(100);
// on_pushButton_5_clicked();
}
});
connect(modbusDevice, &QModbusClient::stateChanged,
this, &MainWindow::onModbusStateChanged); //连接状态发生改变时处理函数(connect or discennect)
timer = new QTimer(this);//建立读取timer
connect(timer, SIGNAL(timeout()), this, SLOT(Readinput()));//连接
timer->setTimerType(Qt::PreciseTimer);//精度
timer_2 = new QTimer(this);//建立刷新ICON
connect(timer_2, SIGNAL(timeout()), this, SLOT(RefreshTaskbarIcon()));//连接刷新ICON
timer_2->start(1500);
// QString IPval;
// QString localHostName = QHostInfo::localHostName();//获取本机的IP地址(可能有多条)qDebug() << "localHostName" << localHostName;
// QHostInfo info = QHostInfo::fromName(localHostName);//只输出IPv4地址 qDebug()<<"IP Address:"<< info.addresses();
// QString *add =new QString();
// foreach(QHostAddress address,info.addresses())
// {
// if(address.protocol() == QAbstractSocket::IPv4Protocol)
// IPval = address.toString();
// }
QFileInfo path(strAppPath + "\config\params.ini");
if (path.isFile() == false){
(QMessageBox::information(NULL, "", "找不到配置config.ini文件"));}
configIni = new QSettings(strAppPath + "\config\params.ini", QSettings::IniFormat, this);//配置文件读取
configIni->setIniCodec("UTF-8");
//ui->lineEdit->adjustSize();//自动大小
ui->IPlineEdit->setText(configIni->value("config/IP").toString());//ip
ui->PortlineEdit->setText(configIni->value("config/PORT").toString());// port
//获取可以用的串口
QList serialPortInfos = QSerialPortInfo::availablePorts();
for (const QSerialPortInfo &serialPortInfo : serialPortInfos)
{
//串口信息
//this->textbrowser("描述:n"+serialPortInfo.description()) ;
//this->textbrowser("制造商:n"+serialPortInfo. manufacturer());
//this->textbrowser("端口:n"+serialPortInfo. portName()) ;
//this->textbrowser("产品标识符:n"+QString::number(serialPortInfo. productIdentifier()));
//this->textbrowser("序列号:n"+ serialPortInfo. serialNumber());
//this->textbrowser( serialPortInfo. systemLocation()) ;
ui->comboBox->addItem(serialPortInfo. portName());
if(serialPortInfo. portName()== configIni->value("config/COM").toString()){
ui->comboBox->removeItem(-1);
}
if(serialPortInfo. portName() ==NULL){
(QMessageBox::warning(NULL, "", "检查COM是否存在"));
}
}
ui->comboBox_2-> insertItem(0,configIni->value("config/Baud").toString());
ui->comboBox_2->setCurrentIndex(0);
IntValidator = new QIntValidator(this);//端口校验
IntValidator->setRange(0, 65535);//端口限制(0,65535)
ui->PortlineEdit->setValidator(IntValidator);
QRegExp rx("^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");//IP校验
QRegExpValidator *ip1 = new QRegExpValidator(rx, this);
ui->IPlineEdit->setValidator(ip1);
QFileInfo path1(strAppPath + "\config\name.ini");
if (path1.isFile() == false){
(QMessageBox::information(NULL, "", "找不到配置name.ini文件"));}
name = new QSettings(strAppPath + "\config\name.ini", QSettings::IniFormat, this);//配置文件读取
name->setIniCodec("UTF-8");
ui->outbtn_1->setText(name->value("config/name1").toString()+"开");
ui->outbtn_2->setText(name->value("config/name2").toString()+"开");
ui->outbtn_3->setText(name->value("config/name3").toString()+"开");
ui->outbtn_4->setText(name->value("config/name4").toString()+"开");
ui->allonbtn->setText(name->value("config/name5").toString()+"全开");
ui->alloffbtn->setText(name->value("config/name6").toString()+"全关");
udpsocket = new QUdpSocket(this);//新建UDP
const quint16 PORT = configIni->value("config/PORT").toInt();//监听端口
this->udpsocket->bind(QHostAddress(configIni->value("config/IP").toString()), PORT);
connect(udpsocket, SIGNAL(readyRead()), this, SLOT(recvMsg()));//连接接收函数
if (udpsocket->errorString() != "Unknown error")//socket erro 捕捉
{
QMessageBox::information(NULL, "", udpsocket->errorString());
}
ui->inlabel->setStyleSheet("QLabel{""background-image:url(:/icon2.png);"
"background-position:top right;"
"background-origin:content;"
"background-repeat:none;"
"}");
ui->inlabel_2->setStyleSheet("QLabel{""background-image:url(:/icon2.png);"
"background-position:top right;"
"background-origin:content;"
"background-repeat:none;"
"}");
ui->inlabel_3->setStyleSheet("QLabel{""background-image:url(:/icon2.png);"
"background-position:top right;"
"background-origin:content;"
"background-repeat:none;"
"}");
ui->inlabel_4->setStyleSheet("QLabel{""background-image:url(:/icon2.png);"
"background-position:top right;"
"background-origin:content;"
"background-repeat:none;"
"}");
}
void MainWindow::Delay(int time)//time*1000为秒数
{
clock_t now = clock();
while(clock()-now
//mian.cpp
#include "mainwindow.h"
#include
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setStyle(QStyleFactory::create("fusion"));
MainWindow w;
w.show();
return a.exec();
}
以上完整代码,工程链接
QT5.15modbusRTU4路输入输出-C++文档类资源-CSDN下载