当前位置: 首页 > news >正文

旅游资讯网站建设方案公司制做网站

旅游资讯网站建设方案,公司制做网站,游戏开服表网站开发,企业网站建设排名文章目录 前言一、引入Modbus模块二、Modbus设备的连接三、各寄存器数据的读取四、各寄存器数据的写入五、示例完整代码总结 前言 本文主要讲述了使用Qt的Modbus模块来进行ModbusTcp的通信#xff0c;实现对PLC的线圈寄存器和保持寄存器的读写#xff0c;基于TCP/IP的Modbus… 文章目录 前言一、引入Modbus模块二、Modbus设备的连接三、各寄存器数据的读取四、各寄存器数据的写入五、示例完整代码总结 前言 本文主要讲述了使用Qt的Modbus模块来进行ModbusTcp的通信实现对PLC的线圈寄存器和保持寄存器的读写基于TCP/IP的Modbus协议的内容我就不做过多解释了详见参考文章。在本文示例中采用QModbusTcpClient类作为Modbus客户端主站PLC作为从站封装了一个自己的MyModbus类希望可以帮助到大家如有错误之处欢迎大家批评指正。 项目效果 提示以下是本篇文章正文内容下面案例可供参考 一、引入Modbus模块 1.这里我实现了自己的MyModbus类的封装使用了pri子模块的方式也是方便日后进行此模块的复用 pri中引入Modbus模块 MyModbus.pri QT serialbus serialportMyModbus类中添加相关头文件 #include QModbusTcpClient #include QModbusDataUnit二、Modbus设备的连接 1.ModbusTcp的连接只需要配置好连接参数IPPort //判断当前连接状态是否为断开状态 if(myClient-state() ! QModbusDevice::ConnectedState) {//配置ModbusTcp的连接参数IPPortmyClient-setConnectionParameter(QModbusDevice::NetworkAddressParameter,ip);myClient-setConnectionParameter(QModbusDevice::NetworkPortParameter,port);myClient-connectDevice(); }三、各寄存器数据的读取 1.Modbus中有4种操作对象这4种都能进行读取操作线圈、离散输入、保持寄存器、输入寄存器 //读取modbus设备各寄存器数据 //typeNum:1_线圈 2_离散输入 3_保持 4_输入 bool MyModbus::readModbusData(int typeNum,int startAdd,quint16 numbers) {if(myClient-state() ! QModbusDevice::ConnectedState){return false;}//确定寄存器类型QModbusDataUnit ReadUnit;if(typeNum 1){ReadUnit QModbusDataUnit(QModbusDataUnit::Coils,startAdd,numbers);}else if(typeNum 2){ReadUnit QModbusDataUnit(QModbusDataUnit::DiscreteInputs,startAdd,numbers);}else if(typeNum 3){ReadUnit QModbusDataUnit(QModbusDataUnit::HoldingRegisters,startAdd,numbers);}else if(typeNum 4){ReadUnit QModbusDataUnit(QModbusDataUnit::InputRegisters,startAdd,numbers);}else{LOGDEBUG读取寄存器类型错误;return false;}LOGDEBUGreadModbusData typeNum:typeNum;//多读if(auto *reply myClient-sendReadRequest(ReadUnit,1)){if(!reply-isFinished()){if((typeNum 1) || (typeNum 2)){QObject::connect(reply,QModbusReply::finished,this,MyModbus::slot_readReadyCoils); //读取线圈}if((typeNum 3) || (typeNum 4)){QObject::connect(reply,QModbusReply::finished,this,MyModbus::slot_readReadyRegisters); //读取寄存器}//reply-deleteLater();return true;}else{reply-deleteLater();return false;}}else{LOGDEBUG读取错误: myClient-errorString();return false;} }四、各寄存器数据的写入 1.Modbus中4种操作对象只有这2种能进行写入操作线圈 、保持寄存器 //对modbus设备各寄存器写入数据 //typeNum:1_线圈 2_保持 (这两类寄存器可读可写,其余的只读) bool MyModbus::writeModbusData(int typeNum,int startAdd,int writeNum) {if(myClient-state() ! QModbusDevice::ConnectedState){return false;}//确定寄存器类型QModbusDataUnit writeUnit;if(typeNum 1){writeUnit QModbusDataUnit(QModbusDataUnit::Coils,startAdd,1); //写入一个数据writeUnit.setValue(0,writeNum);//单写//bool ok;//quint16 hexData writeData.toInt(ok,16); //转16进制}else if(typeNum 2){writeUnit QModbusDataUnit(QModbusDataUnit::HoldingRegisters,startAdd,2); //写入两个数据quint16 uData16[2] {0};uData16[0] writeNum 0xffff;uData16[1] (writeNum 16) 0xffff;writeUnit.setValue(0,uData16[0]);writeUnit.setValue(1,uData16[1]);//LOGDEBUGuData16[0]:uData16[0] uData16[1]:uData16[1] writeNum:writeNum;}else{LOGDEBUG写入寄存器类型错误;return false;}//LOGDEBUGwriteModbusData typeNum:typeNum writeNum:writeNum;if(auto *reply myClient-sendWriteRequest(writeUnit,1)){if(!reply-isFinished()){connect(reply,QModbusReply::finished,this,[reply](){if(reply-error() QModbusDevice::NoError){reply-deleteLater();return true;}else{LOGDEBUG写入返回错误:reply-error();reply-deleteLater();return false;}});}else{reply-deleteLater();return false;}}else{LOGDEBUG写入错误: myClient-errorString();return false;}return true; }五、示例完整代码 这里是示例项目的完整代码包含pro主程序和MyModbus.pri子文件 1.ModbusTest.pro QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11#定义编译选项.QT_DEPRECATED_WARNINGS表示当Qt的某些功能被标记为过时的,那么编译器会发出警告. DEFINES QT_DEPRECATED_WARNINGS#设置字符(MSCV编译器下防止中文乱码) contains( CONFIG,msvc ):QMAKE_CXXFLAGS /source-charset:utf-8 /execution-charset:utf-8 contains( CONFIG,msvc ):QMAKE_CFLAGS /source-charset:utf-8 /execution-charset:utf-8include (./MyModbus/MyModbus.pri)SOURCES \main.cpp \widget.cppHEADERS \widget.hFORMS \widget.ui# Default rules for deployment. qnx: target.path /tmp/$${TARGET}/bin else: unix:!android: target.path /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS target2.MyModbus.pri QT serialbus serialportHEADERS \$$PWD/mymodbus.hSOURCES \$$PWD/mymodbus.cpp3.mymodbus.h #ifndef MYMODBUS_H #define MYMODBUS_H#include QObject #include QModbusTcpClient #include QModbusDataUnit #include QDebug#define LOGDEBUG qDebug()__FILE____LINE__class MyModbus : public QObject {Q_OBJECT public:explicit MyModbus(QObject *parent nullptr);~MyModbus();void initModbus();void connectToModbus(QString ip,int port);bool readModbusData(int typeNum,int startAdd,quint16 numbers);bool writeModbusData(int typeNum,int startAdd,int writeNum);signals:void signal_stateChanged(bool flag);void signal_readCoils(QVectorquint16 vAllData);void signal_readRegisters(int resultNum);private slots:void slot_stateChanged();void slot_readReadyCoils();void slot_readReadyRegisters();private:QModbusTcpClient *myClient;}; #endif // MYMODBUS_H4.mymodbus.cpp #include mymodbus.hMyModbus::MyModbus(QObject *parent) : QObject(parent) {this-initModbus(); }MyModbus::~MyModbus() {}//初始化 void MyModbus::initModbus() {myClient new QModbusTcpClient();//connect(myClient,SIGNAL(stateChanged()),this,SLOT(slot_stateChanged()));connect(myClient,QModbusClient::stateChanged,this,MyModbus::slot_stateChanged); }//连接到modbus设备 void MyModbus::connectToModbus(QString ip,int port) {if(!myClient){return;}//判断当前连接状态是否为断开状态if(myClient-state() ! QModbusDevice::ConnectedState){//配置ModbusTcp的连接参数IPPortmyClient-setConnectionParameter(QModbusDevice::NetworkAddressParameter,ip);myClient-setConnectionParameter(QModbusDevice::NetworkPortParameter,port);myClient-connectDevice();}//else//{// myClient-disconnectDevice();//} }//读取modbus设备各寄存器数据 //typeNum:1_线圈 2_离散输入 3_保持 4_输入 bool MyModbus::readModbusData(int typeNum,int startAdd,quint16 numbers) {if(myClient-state() ! QModbusDevice::ConnectedState){return false;}//确定寄存器类型QModbusDataUnit ReadUnit;if(typeNum 1){ReadUnit QModbusDataUnit(QModbusDataUnit::Coils,startAdd,numbers);}else if(typeNum 2){ReadUnit QModbusDataUnit(QModbusDataUnit::DiscreteInputs,startAdd,numbers);}else if(typeNum 3){ReadUnit QModbusDataUnit(QModbusDataUnit::HoldingRegisters,startAdd,numbers);}else if(typeNum 4){ReadUnit QModbusDataUnit(QModbusDataUnit::InputRegisters,startAdd,numbers);}else{LOGDEBUG读取寄存器类型错误;return false;}LOGDEBUGreadModbusData typeNum:typeNum;//多读if(auto *reply myClient-sendReadRequest(ReadUnit,1)){if(!reply-isFinished()){if((typeNum 1) || (typeNum 2)){QObject::connect(reply,QModbusReply::finished,this,MyModbus::slot_readReadyCoils); //读取线圈}if((typeNum 3) || (typeNum 4)){QObject::connect(reply,QModbusReply::finished,this,MyModbus::slot_readReadyRegisters); //读取寄存器}//reply-deleteLater();return true;}else{reply-deleteLater();return false;}}else{LOGDEBUG读取错误: myClient-errorString();return false;} }//对modbus设备各寄存器写入数据 //typeNum:1_线圈 2_保持 (这两类寄存器可读可写,其余的只读) bool MyModbus::writeModbusData(int typeNum,int startAdd,int writeNum) {if(myClient-state() ! QModbusDevice::ConnectedState){return false;}//确定寄存器类型QModbusDataUnit writeUnit;if(typeNum 1){writeUnit QModbusDataUnit(QModbusDataUnit::Coils,startAdd,1); //写入一个数据writeUnit.setValue(0,writeNum);//单写//bool ok;//quint16 hexData writeData.toInt(ok,16); //转16进制}else if(typeNum 2){writeUnit QModbusDataUnit(QModbusDataUnit::HoldingRegisters,startAdd,2); //写入两个数据quint16 uData16[2] {0};uData16[0] writeNum 0xffff;uData16[1] (writeNum 16) 0xffff;writeUnit.setValue(0,uData16[0]);writeUnit.setValue(1,uData16[1]);//LOGDEBUGuData16[0]:uData16[0] uData16[1]:uData16[1] writeNum:writeNum;}else{LOGDEBUG写入寄存器类型错误;return false;}//LOGDEBUGwriteModbusData typeNum:typeNum writeNum:writeNum;if(auto *reply myClient-sendWriteRequest(writeUnit,1)){if(!reply-isFinished()){connect(reply,QModbusReply::finished,this,[reply](){if(reply-error() QModbusDevice::NoError){reply-deleteLater();return true;}else{LOGDEBUG写入返回错误:reply-error();reply-deleteLater();return false;}});}else{reply-deleteLater();return false;}}else{LOGDEBUG写入错误: myClient-errorString();return false;}return true; }//监听TCP连接的状态,若状态发生改变,发出对应的信号 void MyModbus::slot_stateChanged() {LOGDEBUGmyClient-state();if(myClient-state() QModbusDevice::ConnectedState){emit signal_stateChanged(true);}else if(myClient-state() QModbusDevice::UnconnectedState){emit signal_stateChanged(false);} }//接收到读取线圈/离散输入寄存器请求后执行的槽函数 void MyModbus::slot_readReadyCoils() {QVectorquint16 vAllData;QModbusReply *reply qobject_castQModbusReply *(sender());if(!reply){LOGDEBUG读取线圈/离散输入寄存器错误;return;}if(reply-error() QModbusDevice::NoError){const QModbusDataUnit unit reply-result();vAllData unit.values();emit signal_readCoils(vAllData);}else{LOGDEBUG线圈/离散输入寄存器回复错误:reply-error();}reply-deleteLater(); }//接收到读取保持/输入寄存器请求后执行的槽函数 void MyModbus::slot_readReadyRegisters() {QModbusReply *reply qobject_castQModbusReply *(sender());if(!reply){LOGDEBUG读取保持/输入寄存器错误;return;}if(reply-error() QModbusDevice::NoError){const QModbusDataUnit unit reply-result();auto valueList unit.values();int nSize valueList.size();if(nSize 2){quint16 uData16[2] {0};uData16[0] valueList[0];uData16[1] valueList[1];int resultNum uData16[0] | (uData16[1] 16);//LOGDEBUGuData16[0]:uData16[0] uData16[1]:uData16[1] resultNum:resultNum;emit signal_readRegisters(resultNum);}else{LOGDEBUG保持寄存器返回数据错误,个数:nSize;}}else{LOGDEBUG保持/输入寄存器回复错误:reply-error();}reply-deleteLater(); }/* //读取保持/输入寄存器数据的另一种方式,已废弃 //当前数据格式为大端模式,高位存低地址 //判断正负数,以高8位的16进制是否为f判断 int resultNum 0; if(QString::number(valueList[1],16).left(1) f) //负数 {//判断是否小于-65535,高16位的10进制为65535if(valueList[1] 65535){resultNum valueList[0] - 65536;}else{resultNum (valueList[1] - 65535) * 65536 (valueList[0] - 65536);} } else {//判断是否大于65535,高16位的10进制大于0if(valueList[1] 0){resultNum valueList[1] * 65536 valueList[0];}else{resultNum valueList[0];} } */5.widget.h #ifndef WIDGET_H #define WIDGET_H#include QWidget #include QFileDialog #include QDateTime #include QMessageBox #include MyModbus/mymodbus.hQT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();void initWidget();private slots:void slot_stateChanged(bool flag);void slot_readCoils(QVectorquint16 vAllData);void slot_readRegisters(int resultNum);private slots:void on_pb_connect_clicked();void on_pb_readM_clicked();void on_pb_writeM_clicked();void on_pb_readD_clicked();void on_pb_writeD_clicked();private:Ui::Widget *ui;MyModbus *m_myModsbus; //MyModbus对象}; #endif // WIDGET_H6.widget.cpp #include widget.h #include ui_widget.hWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui-setupUi(this);this-initWidget(); }Widget::~Widget() {delete ui; }void Widget::initWidget() {//初始化MyModbus对象m_myModsbus new MyModbus();connect(m_myModsbus,SIGNAL(signal_stateChanged(bool)),this,SLOT(slot_stateChanged(bool)));connect(m_myModsbus,SIGNAL(signal_readCoils(QVectorquint16)),this,SLOT(slot_readCoils(QVectorquint16)));connect(m_myModsbus,SIGNAL(signal_readRegisters(int)),this,SLOT(slot_readRegisters(int)));}void Widget::slot_stateChanged(bool flag) {if(flag){ui-lb_state-setText(连接成功);ui-te_show-appendPlainText(QTime::currentTime().toString(hh:mm:ss: ) 连接成功);QMessageBox::warning(this,警告,连接成功!);}else{ui-lb_state-setText(连接断开);ui-te_show-appendPlainText(QTime::currentTime().toString(hh:mm:ss: ) 连接断开);QMessageBox::warning(this,警告,连接断开!);} }void Widget::slot_readCoils(QVectorquint16 vAllData) {LOGDEBUGreadCoils size:vAllData.size();for(int i0;ivAllData.size();i){LOGDEBUGi:vAllData[i];ui-te_show-appendPlainText(QTime::currentTime().toString(hh:mm:ss: ) 读取M区返回数据: QString::number(vAllData[i]));ui-le_dataM-setText(QString::number(vAllData[0]));} }void Widget::slot_readRegisters(int resultNum) {LOGDEBUGresultNum:resultNum;ui-te_show-appendPlainText(QTime::currentTime().toString(hh:mm:ss: ) 读取D区返回数据: QString::number(resultNum));ui-le_dataD-setText(QString::number(resultNum)); }void Widget::on_pb_connect_clicked() {QString ip ui-le_ip-text();int port ui-le_port-text().toInt();LOGDEBUGip:ip port:port;ui-te_show-appendPlainText(QTime::currentTime().toString(hh:mm:ss: ) ip: ip port: QString::number(port));//连接到modbus设备m_myModsbus-connectToModbus(ip,port); }void Widget::on_pb_readM_clicked() {int startAdd ui-le_addressM-text().toInt();LOGDEBUGstartAdd:startAdd;if(!m_myModsbus-readModbusData(1,startAdd,1)){QMessageBox::warning(this,警告,M区数据读取失败!);} }void Widget::on_pb_writeM_clicked() {int startAdd ui-le_addressM-text().toInt();int writeNum ui-le_dataM-text().toInt();LOGDEBUGstartAdd:startAdd writeNum:writeNum;//单写if(!m_myModsbus-writeModbusData(1,startAdd,writeNum)){QMessageBox::warning(this,警告,M区数据写入失败!);} }void Widget::on_pb_readD_clicked() {int startAdd ui-le_addressD-text().toInt();LOGDEBUGstartAdd:startAdd;if(!m_myModsbus-readModbusData(3,startAdd,2)){QMessageBox::warning(this,警告,D区数据读取失败!);} }void Widget::on_pb_writeD_clicked() {int startAdd ui-le_addressD-text().toInt();int writeNum ui-le_dataD-text().toInt();;LOGDEBUGstartAdd:startAdd writeNum:writeNum;//进行写入寄存器数据的处理if(!m_myModsbus-writeModbusData(2,startAdd,writeNum)){QMessageBox::warning(this,警告,D区数据写入失败!);} }7.main.cpp #include widget.h #include QApplication #include QMutex//程序输出日志 void outputMessage(QtMsgType type,const QMessageLogContext context,const QString msg) {static QMutex mutex;mutex.lock();//初始化log文件夹QString logFilePath QCoreApplication::applicationDirPath() /LogFile/;QDir dstDir(logFilePath);if(!dstDir.exists()){if(!dstDir.mkpath(logFilePath)){LOGDEBUG程序输出日志创建失败;}else{LOGDEBUG程序输出日志创建成功;}}//获取输出内容QString debugMsg;if(type QtDebugMsg){QString debugDateTime QDateTime::currentDateTime().toString(yyyy-MM-dd hh:mm:ss);debugMsg QString(%1\n%2%3).arg(debugDateTime).arg(msg).arg(context.function);}//保存文件QString curDate QDate::currentDate().toString(yyyyMMdd);QString logFile logFilePath log_ curDate .txt;QFile file(logFile);file.open(QIODevice::WriteOnly | QIODevice::Append);QTextStream textStream(file);textStream debugMsg \n\n;file.flush();file.close();mutex.unlock(); }int main(int argc, char *argv[]) {QApplication a(argc, argv);qInstallMessageHandler(outputMessage);Widget w;w.show();return a.exec(); }8.widget.ui 总结 基于Qt使用这个ModbusTcp协议进行通信还是比较简单的首先就是确定下寄存器的类型直接使用相关的函数进行读写。需要注意的一点是在进行保持寄存器读写的时候我们PLC某个地址上的数是个16位的数所以在进行32位有符号数读写的时候要考虑两个相邻地址的组合文中就对此进行了处理这种情况下PLC那边也别忘记进行相应的设置哈。 hello 共同学习共同进步如果还有相关问题可在评论区留言进行讨论。 参考博客 QT下的Modbus TCP 通讯 C与PLC通过Modbus TCP协议进行PLC内部寄存器的值的读取/写入总结
http://www.tj-hxxt.cn/news/228765.html

相关文章:

  • 哪个网站可以查企业信息网站必须做电子认证吗
  • 做班级网站的实训报告如何做网站的版块规划
  • 怎样查找网站域名辽宁省住房和城乡建设网站
  • 网站建设推广邮件应用小程序下载
  • 苗木企业网站建设源代码上海网站seo设计
  • 网站建设的SOWT分析无人区在线观看高清1080
  • 厦门找一家做网站的公司好三亚旅游网站建设
  • 如何做明星的个人网站线下怎么做推广和宣传
  • 网站建设中网站需求分析报告自己的网站做飘窗
  • 营销型网站建设要求打造公司的网站
  • 微信公众平台 网站 对接云南网站建设哪家权威
  • 政务公开网站建设意义wordpress底端小工具
  • 怎么做移动端网站计算像素开源商城系统源码
  • 徐州企业网站建设谷歌怎么把两个网站做反链
  • 网站在百度无法验证码怎么办啊恶意推广网站
  • 东莞网站设计找谁删除西部数码网站管理助手
  • 票务网站做酒店推荐的目的宝和网站建设
  • vip视频解析网站怎么做肇庆高端品牌网站建设
  • 微信网站游戏ai智能ppt制作
  • 旅游网站的导航怎么做网站论坛建设需要什么资质
  • 重庆住房城乡建设厅网站首页wordpress手机编辑器
  • 淄博网站建设优化公司东莞樟木头网站建设
  • 网站开发公司会计vi设计模板源文件
  • wordpress字体哪个好看百度手机seo软件
  • 云南百度建站小说推文万能关键词
  • 网站icp备案有效时间重庆市住房和城乡建设厅网站
  • wordpress 在线咨询网站标签优化怎么做
  • 免注册制作网站家装公司排行榜
  • 福田做棋牌网站建设哪家公司便宜建网站多少钱
  • 做网站容易还是做小程序容易网页传奇游戏排行榜比亚迪