【Qt Modbus通信】libmodbus实现modbus的主机功能/从机功能 源码分享

您所在的位置:网站首页 学校介绍报告 【Qt Modbus通信】libmodbus实现modbus的主机功能/从机功能 源码分享

【Qt Modbus通信】libmodbus实现modbus的主机功能/从机功能 源码分享

2024-01-13 20:22| 来源: 网络整理| 查看: 265

前言

modbus在上下位机数据交互时被广泛使用,因此写了这篇笔记和大家一起学习。

参考文献

Libmodbus源码分析(二)-常用接口函数分析 Libmodbus源码分析(四)-RTU相关函数分析 【Qt Modbus通信】QModbus实现modbus的主机功能 源码分享

第三方库 libmodbus

网上有一个现成的libmodbus C库,支持Linux, Mac OS X, FreeBSD, QNX 和 Win32。 下载地址为:http://libmodbus.org/download/

基于libmodbus开源的学习例程Qmodbus

亲测源码支持QT4/QT5版本,在window和Linux环境下都可以使用 官网:http://qmodbus.sourceforge.net/ 源码:https://github.com/ed-chemnitz/qmodbus/ 如果下载不了也可以在我的GitHub上下载 该DEMO支持 RTU/TCP/ASCII模式 在这里插入图片描述

下面我将DEMO中的关键代码移植出来,实现了一个运行在子线程中且包含了主机功能和从机功能的程序。 项目配置

我将需要用到的libmodbus源码放在了这个路径下 大家可以在我的GitHub上自行下载 在这里插入图片描述 需要用到的文件有 在这里插入图片描述

需要注意的地方 加上以下内容就可以在运行在window或ubuntu环境下

unix { SOURCES += 3rdparty/qextserialport/posix_qextserialport.cpp \ 3rdparty/qextserialport/qextserialenumerator_unix.cpp DEFINES += _TTY_POSIX_ } win32 { SOURCES += 3rdparty/qextserialport/win_qextserialport.cpp \ 3rdparty/qextserialport/qextserialenumerator_win.cpp DEFINES += _TTY_WIN_ WINVER=0x0501 LIBS += -lsetupapi -lws2_32 } 主机功能

程序运行效果 在这里插入图片描述 完成功能:modbus主机在子线程中每隔一秒钟向modbus Slave 请求 40030-40035寄存器的内容。

关键代码演示

1.将modbusPollThread类放到子线程中 slaveID 指定读取从机的ID地址 为什么要子线程中运行:因为读取从机数据是一个比较耗时的操作如果放在主线程运行会导致QT的UI界面卡顿

modbusPollThread::modbusPollThread(int slaveID, QObject *parent) { qDebug() qDebug() Q_UNUSED(modbus); QString dump; for( int i = 0; i int readNum = 5; modbus_set_slave(my_bus,m_slaveId);//设置需要连接的从机地址 int ret = modbus_read_registers(my_bus,40030,readNum,modbus_hold_reg); //读取保持寄存器的第0位开始的前5位 //modbus_read_input_registers(my_bus,0,50,modbus_input_reg); //读取输入寄存器的第0位开始的前5位 QString err; if(ret != readNum) //读取错误 { if( ret err += tr( "I/O error" ); err += ": "; err += tr( "did not receive any data from slave." ); } else { err += tr( "Protocol error" ); err += ": "; err += tr( "Slave threw exception '" ); err += modbus_strerror( errno ); err += tr( "' or function not implemented." ); } } else { err += tr( "Protocol error" ); err += ": "; err += tr( "Number of registers returned does not " "match number of registers requested!" ); } } if( err.size() > 0 ) emit SIGNAL_SENDGETSLAVEINFO("读取失败:" + err); else //读取正常 { QString info = QString("从机ID: %1 modbus read : %2 %3 %4 %5 %6 \r\n ")\ .arg(QString::number(m_slaveId)).arg(modbus_hold_reg[0])\ .arg(modbus_hold_reg[1]).arg(modbus_hold_reg[2])\ .arg(modbus_hold_reg[3]).arg(modbus_hold_reg[4]); emit SIGNAL_SENDGETSLAVEINFO(info); } }

5.UI主线程中 使用主机功能和从机功能 5.1实例化

//传入主机ID 1 m_slave = new modbusSlaveThread(1); connect(this,&MainWindow::signal_connectSlave,m_slave,&modbusSlaveThread::connnectModbusSlave); connect(this,&MainWindow::signal_disconnectSlave,m_slave,&modbusSlaveThread::disconnnectModbusSlave); //传入从机ID 1 m_poll = new modbusPollThread(1); connect(this,&MainWindow::signal_connectPoll,m_poll,&modbusPollThread::connnectModbusPoll); connect(this,&MainWindow::signal_disconnectPoll,m_poll,&modbusPollThread::disconnnectModbusPoll); connect(m_poll,&modbusPollThread::SIGNAL_SENDGETSLAVEINFO,this,&MainWindow::onShowSlaveInfo);

5.2 开启主机/关闭主机

void MainWindow::on_pushButton_Poll_clicked() { if(ui->pushButton_Poll->text() == "开启主机") { if(ui->comboBox_name_POLL->currentText().isEmpty()==true) { ui->textEdit_POLL->setText(ui->textEdit_POLL->toPlainText().append("未设置设备号\r\n")); ui->textEdit_POLL->moveCursor(QTextCursor::End); //textedit 滚动条自动往下滚动 return; } QString namestring = ui->comboBox_name_POLL->currentText(); uint modbus_baud = ui->comboBox_baud_POLL->currentText().toUInt(); //发送信号 开启主机 emit signal_connectPoll(namestring,modbus_baud); ui->pushButton_Poll->setText("关闭主机"); }else { //发送信号关闭主机 emit signal_disconnectPoll(); ui->pushButton_Poll->setText("开启主机"); } } 从机功能

程序运行效果 使用modbus Poll定时向程序读取 寄存器1-5的内容 在这里插入图片描述

关键代码演示

从机代码和主机代码差不多 1.请求连接主机 1.1 设置保持寄存器的值 修改tab_registers数组 1.2 设置输入寄存器的值 修改tab_input_bits数组

void modbusSlaveThread::connnectModbusSlave(QString portName, int baud) { qDebug() int rc; //qDebug()


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3