实现的基本的modbus 读取写入寄存器的类
QT += serialbus serialport
modbusMaster.h
#ifndef MODBUSMASTER_H
#define MODBUSMASTER_H
#include <QModbusClient>
#include <QModbusDataUnit>
#include <QObject>
#include <QSerialPort>
#include <QModbusRtuSerialMaster>
#include <QModbusTcpClient>
/*
*
* modbus master 主站
*
* 1. modbusMaster * m_master = new modbusMaster(this);
*
* 2.初始化合适的模式 串口 网口
* initModbusSerialMaster(19200,QSeraiPort::DATA8,......)
* 连接
*
* 3. connectDevice()
* 写寄存器数据 01 02 03 地址开始为0 后面3个
*
* 4.writeRegisterData("01 02 03",0,3);
* 读寄存器数据 0地址开始 后面3个
*
* 5.readRegisterData(0,3);
* 读出来的寄存器数据 会通过readData_signal 信号拿到
* address 地址 value 值
*
*
*
*/
class modbusMaster : public QObject
{
Q_OBJECT
public:
explicit modbusMaster(QObject *parent = nullptr);
enum modbusConnection
{
Serial,
Tcp
};
/**
* @projectName testMyClass
* @brief 初始化串口modbusMaster
* 其他参数 波特率 数据位 校验位 停止位
* @author SMY
* @date 2019-03-27
*/
bool initModbusSerialMaster(QString portName, qint32 baudRate, QSerialPort::DataBits dataBits,
QSerialPort::Parity parity, QSerialPort::StopBits stopBits);
/**
* @projectName testMyClass
* @brief 初始化网口modbusMaster
* ip地址,端口号
* @author SMY
* @date 2019-03-27
*/
bool initModbusNetworkMaster(QString address,int port);
/**
* @projectName testMyClass
* @brief 连接设备
* @author SMY
* @date 2019-03-27
*/
bool connectDevice();
/**
* @projectName testMyClass
* @brief 写寄存器数据,数据,开始地址,个数
* @author SMY
* @date 2019-03-27
*/
bool writeRegisterData(QString str,int startAddress,int num);
/**
* @projectName testMyClass
* @brief 读寄存器 开始地址,个数
* @author SMY
* @date 2019-03-27
*/
void readRegisterData(int startAddress,int num);
signals:
//发生错误
void error_signal(QString errorString);
/*state :1 connect ,0:unconnect
*状态发生改变
*/
void stateChanged_signal(int state);
/*读到寄存器的值信号*/
void readData_signal(int address,int value);
public slots:
/**
* @projectName testMyClass
* @brief device error
* @author SMY
* @date 2019-03-27
*/
void handleDeviceError(QModbusDevice::Error newError);
/**
* @projectName testMyClass
* @brief 连接状态改变
* @author SMY
* @date 2019-03-27
*/
void onStateChanged(int state);
void readyRead();
private:
QModbusClient* m_master;
modbusConnection m_mode;
};
#endif // MODBUSMASTER_H
modbusMaster.cpp
#include "modbusmaster.h"
#include <QDebug>
modbusMaster::modbusMaster(QObject *parent) : QObject(parent)
{
}
bool modbusMaster::initModbusSerialMaster(QString portName, qint32 baudRate,
QSerialPort::DataBits dataBits,
QSerialPort::Parity parity,
QSerialPort::StopBits stopBits)
{
m_master = new QModbusRtuSerialMaster(this);
if(!m_master)
{
qDebug()<<"init master error";
return 0;
}
m_master->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
portName);
m_master->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
baudRate);
m_master->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
dataBits);
m_master->setConnectionParameter(QModbusDevice::SerialParityParameter,
parity);
m_master->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
stopBits);
return 1;
}
bool modbusMaster::initModbusNetworkMaster(QString address, int port)
{
m_master = new QModbusTcpClient(this);
m_mode = Tcp;
if(!m_master)
{
qDebug()<<"init master error";
return 0;
}
m_master->setConnectionParameter(QModbusDevice::NetworkAddressParameter,
address);
m_master->setConnectionParameter(QModbusDevice::NetworkPortParameter,
port);
return 1;
}
bool modbusMaster::connectDevice()
{
return m_master->connectDevice();
}
bool modbusMaster::writeRegisterData(QString str, int startAddress, int num)
{
QByteArray byte = QByteArray::fromHex(str.toLatin1().data());
QString hexStr = byte.toHex().data();
//发送的数据信息
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters
,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 address sendWriteRequest 是想服务器写数据
if(auto* reply = m_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: "<<m_master->errorString();
return 0;
}
}
void modbusMaster::readRegisterData(int startAddress, int num)
{
if(!m_master)
return;
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters,startAddress,num);
if(auto* reply = m_master->sendReadRequest(readUnit,1))
{
if(!reply->isFinished())
{
connect(reply,&QModbusReply::finished,this,&modbusMaster::readyRead);
}
else
{
delete reply;
}
}
else
{
qDebug()<<m_master->errorString();
}
}
void modbusMaster::handleDeviceError(QModbusDevice::Error newError)
{
if(newError == QModbusDevice::NoError || !m_master)
return;
emit error_signal(m_master->errorString());
}
void modbusMaster::onStateChanged(int state)
{
if(state == QModbusDevice::UnconnectedState)
emit stateChanged_signal(0);
else if(state == QModbusDevice::ConnectedState)
emit stateChanged_signal(1);
}
void modbusMaster::readyRead()
{
auto reply = qobject_cast<QModbusReply*>(sender());
if(!reply)
return;
if(reply->error() == QModbusDevice::NoError)
{
const QModbusDataUnit unit = reply->result();
for(uint i = 0; i< unit.valueCount();i++)
{
const QString entry = tr("Address:%1,Value:%2").arg(unit.startAddress()+i)
.arg(QString::number(unit.value(i),unit.registerType()
<= QModbusDataUnit::Coils?10:16));
//qDebug()<<entry;
emit readData_signal(unit.startAddress()+i,unit.value(i));
}
}
else if(reply->error() == QModbusDevice::ProtocolError)
{
qDebug()<<"error protocolError"<<reply->errorString();
}
else
{
qDebug()<<"error:"<<reply->errorString();
}
reply->deleteLater();
}