这个版本是根据Qt官方例程移植过来的。主要是通过Qt上位机实现对modbus从设备的数据读写。这是笔者在做前期开发时用的,由于在调试的过程中,发现该模块有些不稳定,老是在短时间间隔内出现连接不上设备的问题。于是决定弃用,采用了libmodbbus库+Qt的方式,改版之后确实稳定很多,速率也提上去,这个版本子在一般要求的场合是可以使用,由于笔者开发项目对实时性有严格的要求,所以选择了后者。笔者将在后期将配置代码的过程分享出来。
modbusmaster作为客户端几个重要的头文件:
1、#include <QModbusDataUnit> //数据单元
2、#include <QModbusTcpClient> //客户端
3、#include <QModbusRtuSerialMaster> //串口
#include "modbusmaster.h"
#include "widget.h"
#include <QStatusBar>
#include"QDebug"
#include<QTextEdit>
ModbusMaster::ModbusMaster(QObject *parent) : QObject(parent)
{
}
bool ModbusMaster::InitModbusTCPMaster(QString IPaddress, int port)
{
if(Master)
{
Master->disconnectDevice();
delete Master;
}
Master = new QModbusTcpClient(this);
if(!Master)
{
qDebug()<<"Create modbusdevice fail";
return 0;
}
if(Master->state() != QModbusDevice::ConnectedState)
{
Master->setConnectionParameter(QModbusDevice::NetworkAddressParameter,IPaddress);
Master->setConnectionParameter(QModbusDevice::NetworkPortParameter,port);
Master->connectDevice();
Master->setTimeout(500);
Master->setNumberOfRetries(2);
if (!Master->connectDevice())
{
qDebug()<<" Modbus is not connect";
}
else
{
qDebug()<<" Modbus is connect";
}
}
else
{
Master->disconnectDevice();
qDebug()<<" Modbus is not connect";
}
return 1;
}
bool ModbusMaster::connectDevice()
{
return Master->connectDevice();
}
void ModbusMaster::disconnectDevice()
{
Master->disconnectDevice();
}
bool ModbusMaster::writeRegisterData(QString str, int startAddress, int num)
{
QByteArray byte = QByteArray::fromHex(str.toLatin1().data());
QString hexStr = byte.toHex().data();
//发送的数据信息
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegister,startAddress,num);
//得到的寄存器的类型传给table
QModbusDataUnit::RegisterType table = writeUnit.registerType();
for(int i = 0;i < writeUnit.valueCount(); i++)
{
int j = 2*i;
QString str = hexStr.mid(j,2);
bool ok;
int hex = str.toInt(&ok,16);
writeUnit.setValue(i,hex);
}
//1 代表server slave address sendWriteRequest 是向服务器从机设备地址写数据
if(auto* reply = Master->sendWriteRequest(writeUnit,1))
{
if(!reply->isFinished())
{
connect(reply,&QModbusReply::finished,this,[this,reply]()
{
if(reply->error() == QModbusDevice::ProtocolError)
{
qDebug()<<"write response ProtocolError:"<<reply->errorString();
return 0;
}
else if(reply->error() != QModbusDevice::NoError)
{
qDebug()<<"write response error:"<<reply->errorString();
return 0;
}
reply->deleteLater();
});
}
else
{
reply->deleteLater();
return 1;
}
}
else
{
qDebug()<<"write error: "<<Master->errorString();
return 0;
}
}
void ModbusMaster::readRegisterData(int startAddress,int num,int ServerAddress)
{
if(!Master)
return;
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters,startAddress,num);
if(auto* reply = Master->sendReadRequest(readUnit,ServerAddress))
{
if(!reply->isFinished())
{
connect(reply,&QModbusReply::finished,this,&ModbusMaster::readyRead);
//connect(this,&QModbusReply::finished,this,&MainWindow::readyRead);
}
else
{
delete reply;
}
}
else
{
qDebug()<<Master->errorString();
//statusBar()->showMessage(tr("Read error: ") + Master->errorString(), 5000);
}
}
void ModbusMaster::handleDeviceError(QModbusDevice::Error newError)
{
if(newError == QModbusDevice::NoError || !Master)
return;
emit error_signal(Master->errorString());
}
void ModbusMaster::onStateChanged(int state)
{
if(state == QModbusDevice::UnconnectedState)
emit stateChanged_signal(0);
else if(state == QModbusDevice::ConnectedState)
emit stateChanged_signal(1);
}
QString ModbusMaster::readyRead()
{
QString entry = "0";
auto reply = qobject_cast<QModbusReply*>(sender());
if(reply)
{
if(reply->error() == QModbusDevice::NoError)
{
const QModbusDataUnit unit = reply->result();
entry =QString::number(unit.value(1));//返回的数据单元
//qDebug()<<"bobo"<<entry;
NowWeight =entry;
}
else if(reply->error() == QModbusDevice::ProtocolError)
{
qDebug()<<"error protocolError"<<reply->errorString();
}
else
{
qDebug()<<"bo error:"<<reply->errorString();
}
reply->deleteLater();
}
return NowWeight;
}
bool ModbusMaster::IsNotModbusMaster()
{
if(!Master)
return 0;
}