modbus.h
#ifndef MODBUS_H
#define MODBUS_H
#include <QDebug>
#include <QObject>
#include <QModbusReply>
#include <QModbusRtuSerialMaster>
#include <QSerialPort>
class modbus : public QObject {
Q_OBJECT
public:
explicit modbus(QObject *parent = nullptr);
void SerialPortUpdate(); // 更新串口信息
void Conn(QString portName, qint32 baud); // 连接串口
void Disconn(); // 断开连接
// void ReadReady();
void ReadCoil(quint8 SlaveAddr, quint8 StartAddr, quint8 Number); // 01
void ReadDiscreteInputs(quint8 SlaveAddr, quint8 StartAddr,
quint8 Number); // 02
void ReadHoldingRegister(quint8 SlaveAddr, quint8 StartAddr,
quint8 Number); // 03
void ReadInputRegister(quint8 SlaveAddr, quint8 StartAddr,
quint8 Number); // 04
void WriteSingleCoil(quint8 SlaveAddr, quint8 CoilAddr, quint8 Data); // 05
void WriteSingleRegister(quint8 SlaveAddr, quint8 RegAddr, qint16 Data); // 06
void WriteMultipleCoil(quint8 SlaveAddr, quint8 StartAddr, qint8 *Data); // 0f
void WriteMultipleRegisters(quint8 SlaveAddr, quint8 StartAddr,
qint16 *Data); // 10
signals:
void Error_signal(QString ErrorString);
void StateChanged_signal(int State);
void ReadData_signal(int Address, int Value);
public slots:
void DeviceErrorHandle(QModbusDevice::Error newError);
void GetState(int State);
void ReadReady(); // 接收
private:
QModbusRtuSerialMaster *master;
};
#endif // MODBUS_H
modbus.cpp
#include "modbus.h"
modbus::modbus(QObject *parent) : QObject{parent} {}
void modbus::SerialPortUpdate() // 更新串口list
{
qInfo() << "modbus::mbSerialPortUpdate()";
// 更新端口号
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
QSerialPort serial;
serial.setPort(info);
if (serial.open(QIODevice::ReadWrite)) {
serial.close();
}
qDebug("调试:端口更新完成");
}
const auto infos = QSerialPortInfo::availablePorts();
qDebug("串口信息:");
for (const QSerialPortInfo &info : infos) {
QString s = QObject::tr("Port: ") + info.portName() +
QObject::tr("Location: ") + info.systemLocation() +
QObject::tr("Description: ") + info.description() +
QObject::tr("Manufacturer: ") + info.manufacturer() +
QObject::tr("Serial number: ") + info.serialNumber() +
QObject::tr("Vendor Identifier: ") +
(info.hasVendorIdentifier()
? QString::number(info.vendorIdentifier(), 16)
: QString()) +
QObject::tr("Product Identifier: ") +
(info.hasProductIdentifier()
? QString::number(info.productIdentifier(), 16)
: QString());
qDebug() << s;
}
}
void modbus::Conn(QString portName, qint32 baud) {
qInfo() << "modbus::Conn(QString portName, qint32 baud)" << portName << baud;
master = new QModbusRtuSerialMaster(); // new 主站对象
connect(master, &QModbusClient::errorOccurred, this,
[=](QModbusDevice::Error) { qDebug() << master->errorString(); });
if (!master) {
qDebug() << "Could not create Modbus master";
}
if (master->state() == QModbusDevice::UnconnectedState) {
// 设置串口参数
master->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
portName);
master->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
baud);
master->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
QSerialPort::Data8);
master->setConnectionParameter(QModbusDevice::SerialParityParameter,
QSerialPort::Parity::NoParity);
master->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
QSerialPort::OneStop);
master->setTimeout(1000); // 超时时间
master->setNumberOfRetries(3); // 重试3次
if (master->connectDevice()) {
qDebug() << "连接成功";
} else {
qDebug() << "连接失败" << master->errorString();
}
}
}
void modbus::Disconn() {
qInfo() << "modbus::Disconn()";
if (master->state() != QModbusDevice::UnconnectedState) {
master->disconnectDevice();
delete master;
master = nullptr;
qDebug() << "断开连接";
}
}
void modbus::GetState(int state) {
if (state == QModbusDevice::UnconnectedState)
emit StateChanged_signal(0);
else if (state == QModbusDevice::ConnectedState)
emit StateChanged_signal(1);
}
void modbus::DeviceErrorHandle(QModbusDevice::Error newError) {
if (newError == QModbusDevice::NoError || !master)
return;
emit Error_signal(master->errorString());
}
void modbus::ReadReady() {
qInfo() << "modbus::ReadReady()";
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)));
qDebug() << entry;
emit ReadData_signal(unit.startAddress() + i, unit.value(i));
}
} else if (reply->error() == QModbusDevice::ProtocolError) {
qDebug() << "ProtocolError:" << reply->errorString();
} else {
qDebug() << "Error:" << reply->errorString();
}
reply->deleteLater();
}
// 01
void modbus::ReadCoil(quint8 SlaveAddr, quint8 StartAddr, quint8 Number) {
qInfo()
<< "modbus::ReadCoil(quint8 SlaveAddr, quint8 StartAddr, quint8 Number)"
<< SlaveAddr << StartAddr << Number;
if (!master)
return;
QModbusDataUnit mdu(QModbusDataUnit::Coils, StartAddr, Number);
if (auto *reply = master->sendReadRequest(mdu, SlaveAddr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &modbus::ReadReady);
} else {
delete reply;
}
} else {
qDebug() << master->errorString();
}
}
// 02
void modbus::ReadDiscreteInputs(quint8 SlaveAddr, quint8 StartAddr,
quint8 Number) {
qInfo() << "modbus::ReadDiscreteInputs(quint8 SlaveAddr, quint8 StartAddr, "
"quint8 Number)"
<< SlaveAddr << StartAddr << Number;
if (!master)
return;
QModbusDataUnit mdu(QModbusDataUnit::DiscreteInputs, StartAddr, Number);
if (auto *reply = master->sendReadRequest(mdu, SlaveAddr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &modbus::ReadReady);
} else {
delete reply;
}
} else {
qDebug() << master->errorString();
}
}
// 03
void modbus::ReadHoldingRegister(quint8 SlaveAddr, quint8 StartAddr,
quint8 Number) {
qInfo() << "modbus::ReadHoldingRegister(quint8 SlaveAddr, quint8 "
"StartAddr, quint8 Number)"
<< SlaveAddr << StartAddr << Number;
if (!master)
return;
QModbusDataUnit mdu(QModbusDataUnit::HoldingRegisters, StartAddr, Number);
if (auto *reply = master->sendReadRequest(mdu, SlaveAddr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &modbus::ReadReady);
} else {
delete reply;
}
} else {
qDebug() << master->errorString();
}
}
// 04
void modbus::ReadInputRegister(quint8 SlaveAddr, quint8 StartAddr,
quint8 Number) {
qInfo() << "modbus::ReadInputRegister(quint8 SlaveAddr, quint8 StartAddr, "
"quint8 Number)"
<< SlaveAddr << StartAddr << Number;
if (!master)
return;
QModbusDataUnit mdu(QModbusDataUnit::InputRegisters, StartAddr, Number);
if (auto *reply = master->sendReadRequest(mdu, SlaveAddr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &modbus::ReadReady);
} else {
delete reply;
}
} else {
qDebug() << master->errorString();
}
}
// 05
void modbus::WriteSingleCoil(quint8 SlaveAddr, quint8 CoilAddr, quint8 Data) {
qInfo() << "modbus::WriteSingleCoil(quint8 SlaveAddr, quint8 StartAddr, "
"quint8 Data)"
<< SlaveAddr << CoilAddr << Data;
if (!master)
return;
QModbusDataUnit mdu(QModbusDataUnit::Coils, CoilAddr, 1);
mdu.setValue(0, Data);
if (auto *reply = master->sendWriteRequest(mdu, SlaveAddr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &modbus::ReadReady);
} else {
delete reply;
}
} else {
qDebug() << master->errorString();
}
}
// 06
void modbus::WriteSingleRegister(quint8 SlaveAddr, quint8 RegAddr,
qint16 Data) {
qInfo() << "modbus::WriteSingleRegister(quint8 SlaveAddr, quint8 RegAddr, "
"int Data)"
<< SlaveAddr << RegAddr << Data;
if (!master)
return;
QModbusDataUnit mdu(QModbusDataUnit::HoldingRegisters, RegAddr, 1);
mdu.setValue(0, Data);
if (auto *reply = master->sendWriteRequest(mdu, SlaveAddr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &modbus::ReadReady);
} else {
delete reply;
}
} else {
qDebug() << master->errorString();
}
}
// 15
void modbus::WriteMultipleCoil(quint8 SlaveAddr, quint8 StartAddr,
qint8 *Data) {
qInfo() << "modbus::WriteMultipleCoil(quint8 SlaveAddr, quint8 StartAddr, "
"quint8 *Data)"
<< SlaveAddr << StartAddr << Data;
if (!master)
return;
// 获取数据长度
qint16 Num = sizeof(Data);
QModbusDataUnit mdu(QModbusDataUnit::Coils, StartAddr, Num);
// 设定数据
for (int i = 0; i < Num; ++i) {
mdu.setValue(i, Data[i]);
}
if (auto *reply = master->sendWriteRequest(mdu, SlaveAddr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &modbus::ReadReady);
} else {
delete reply;
}
} else {
qDebug() << master->errorString();
}
}
// 16
void modbus::WriteMultipleRegisters(quint8 SlaveAddr, quint8 StartAddr,
qint16 *Data) {
qInfo()
<< "modbus::WriteMultipleRegisters(quint8 SlaveAddr, quint8 StartAddr, "
"qint16 *Data)"
<< SlaveAddr << StartAddr << Data;
if (!master)
return;
// 获取数据长度
qint16 Num = sizeof(Data);
QModbusDataUnit mdu(QModbusDataUnit::HoldingRegisters, StartAddr, Num);
// 设定数据
for (int i = 0; i < Num; ++i) {
mdu.setValue(i, Data[i]);
}
if (auto *reply = master->sendWriteRequest(mdu, SlaveAddr)) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, &modbus::ReadReady);
} else {
delete reply;
}
} else {
qDebug() << master->errorString();
}
}