来自QQ群 Linux && 技术分享 311078264
打开链接加入QQ群:https://jq.qq.com/?_wv=1027&k=5Gr3bAx
此文档由elikang整理,为了文章简单直接,许多细节未能在文章中体现,如有疑问请进群讨论。
Qt Modbus在QtCreator的示例里面有例子,直接搜modbus就可以看到了,简单学一下就能学会了。
首先,QT5是自带Modbus相关类的,使用时需要在pro文件里面添加一行:
QT += serialbus
My_Modbus.h
/*
* My_Modbus.h
*
* Created on: 2021年3月11日
* Author: elikang
*/
#ifndef MY_MODBUS_H
#define MY_MODBUS_H
#include <QObject>
#include <QSerialPort>
#include <QModbusDataUnit>
#include <QModbusRtuSerialMaster>
class My_Modbus : public QObject
{
Q_OBJECT
public:
My_Modbus();
~My_Modbus();
void modbusConnect(void);
void modbusDisconnect(void);
void modbusRead(int serverAddress, QModbusDataUnit::RegisterType table, int startAddress, int numOfEntries);
void modbusWrite(int serverAddress, QModbusDataUnit::RegisterType table, int startAddress, int numOfEntries, QVector<quint16> data);
signals:
void modbusReadReady(QModbusDataUnit dataUnit);
public slots:
void modbusStateChanged(void);
void modbusReadData(void);
void modbusMessage(void);
void modbusMessage(QString mess);
public:
struct Settings {
QString portName;
int parity = QSerialPort::EvenParity;
int baud = QSerialPort::Baud115200;
int dataBits = QSerialPort::Data8;
int stopBits = QSerialPort::OneStop;
int responseTime = 1000;
int numberOfRetries = 1;
};
private:
QModbusClient *modbusDevice = nullptr;
Settings m_settings;
}
#endif
My_Modbus.cpp
/*
* My_Modbus.cpp
*
* Created on: 2021年3月11日
* Author: elikang
*/
#include “my_modbus.h”
#include “qdebug.h”
My_Modbus::My_Modbus()
{
modbusDevice = new QModbusRtuSerialMaster(nullptr);
connect(modbusDevice, SIGNAL(errorOccurred()), this, SLOT(modbusMessage()));
if(modbusDevice)
{
qDebug("创建 Modbus Master 成功。");
connect(modbusDevice, &QModbusClient::stateChanged, this, &My_Modbus::modbusStateChanged);
}
else
{
qDebug("创建 Modbus Master 失败。");
}
}
My_Modbus::~My_Modbus()
{
delete modbusDevice;
}
void My_Modbus::modbusConnect(void)
{
if(!modbusDevice) return;
if(modbusDevice->state() != QModbusDevice::Connected)
{
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, m_settings.portName);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_settings.baud);
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, m_settings.parity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, settings.dataBits);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, m_settings.stopBits);
modbusDevice->setTimeout(m_settings.responseTime);
modbusDevice->setNumberOfRetries(m_settings.numberOfRetries);
if(modbusDevice->connectDevice())
{
qDebug("Modbus 连接成功。");
}
else
{
qDebug("Modbus 连接失败。");
}
}
}
void My_Modbus::modbusDisconnect(void)
{
if (modbusDevice) modbusDevice->disconnectDevice();
delete modbusDevice;
modbusDevice = nullptr;
}
void My_Modbus::modbusStateChanged(int state)
{
if(state == QModbusDevice::UnconnectedState)
{
qDebug("Modbus 已断开。");
}
else if(state == QModbusDevice::ConnectedState)
{
qDebug("Modbus 已连接。");
}
}
void My_Modbus::modbusMessage(void)
{
qDebug() << modbusDevice->errorString();
}
void My_Modbus::modbusMessage(QString mess)
{
qDebug() << mess;
}
void My_Modbus::modbusRead(int serverAddress, QModbusDataUnit::RegisterType table, int startAddress, int numOfEntries, QVector<quint16> data)
{
if(!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState)
{
qDebug("Modbus Device is not connected!");
return;
}
QModbusDataUnit dataUnit = QModbusDataUnit(table, startAddress, numOfEntries);
if(auto *reply = modbusDevice->sendReadRequest(dataUnit, serverAddress))
{
if(reply->isFinished())
{
connect(reply, &QModbusReply::finished, this, &My_Modbus::modbusReadData);
}
}
else
{
modbusMessage(tr("Write error:") + modbusDevice->errorString());
}
}
void My_Modbus::modbusReadData()
{
QModbusDataUnit dataUnit;
auto reply = qobject_cast<QModbusReply *>(sender());
if(!reply) return;
if(reply->error() == QModbusDevice::NoError)
{
dataUnit = reply->result();
emit modbusReadReady(dataUnit);
}
else if(reply->error() == QModbusDevice::ProtocolError)
{
modbusMessage(tr("Read response error: %1 (Modbus exception :0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1 ,16));
}
else
{
modbusMessage(tr("Read response: %1 (code :0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1 ,16));
}
reply->deleteLater();
}
//服务器地址、寄存器类型、起始地址、变量数量、写入数据
void My_Modbus::modbusWrite(int serverAddress, QModbusDataUnit::RegisterType table, int startAddress, int numOfEntries, QVector<quint16> data)
{
if(!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState)
{
qDebug("Modbus Device is not connected!");
return;
}
//QModbusDataUnit,是用来处理通过串口一次传输的数据
QModbusDataUnit dataunit = QModbusDataUnit(table, startAddress, numOfEntries);
for(uint i = 0; i < dataunit.valueCount(); i++)
{
dataunit.setValue( i, data.at(i));
}
if(auto *reply = modbusDevice->sendWriteRequest(dataunit, serverAddress))
{
connect(reply, &QModbusReply::finished, this, [this, reply](){
if(reply->error() == QModbusDevice::ProtocolError){
modbusMessage(tr("Write response error:%1 (modbus exception:0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
}else{
modbusMessage(tr("Write response:%1 (code:0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
}
reply->deleteLater();
});
}
else{
statusBar()->showMessage(tr("Write error:") + modbusDevice->errorString(), 5000);
}
}