相关Qt Class
- QModbusRtuSerialSlave (服务器类)
- QModbusServer
- QModbusDevice
- QModbusClient
- QModbusRtuSerialMaster(客户端类)
- QModbusRequest
- QModbusResponse
- QModbusReply
- QModbusDataUnit
通信流程
创建QModbusRtuSerialMaster对象m_modbusDevice,并设置串口通信参数:
m_modbusDevice.setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::EvenParity);
m_modbusDevice.setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600);
m_modbusDevice.setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
m_modbusDevice.setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
串口连接:
bool connectDevice()
{
//implement
}
连接成功后,发送请求:
QModbusResponse sendModbusRawRequest(const QModbusRequest &request) const
{
//implement
}
断开连接:
void disconnectDevice()
{
//implement
}
示例代码
tempCtrl.h
#ifndef TEMPCTRL_H
#define TEMPCTRL_H
#include <QModbusRtuSerialMaster>
class TempCtrl
{
private:
TempCtrl();
public:
~TempCtrl();
static TempCtrl* instance();
public:
void connectDevice();
void disconnectDevice();
private:
QModbusResponse sendModbusRawRequest(const QModbusRequest &request) const;
private:
bool m_channelConnected;
int m_channelAddr;
mutable QModbusRtuSerialMaster m_modbusDevice;
};
#endif // TEMPCTRL_H
tempCtrl.cpp
#include "TempCtrl.h"
#include <QSerialPortInfo>
#include <QSerialPort>
#include <QCoreApplication>
#include <bitset>
#include <chrono>
#include <thread>
TempCtrl::TempCtrl()
, m_channelConnected(false)
, m_channelAddr(0)
, m_modbusDevice()
{
m_modbusDevice.setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::EvenParity);
m_modbusDevice.setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600);
m_modbusDevice.setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
m_modbusDevice.setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
}
TempCtrl::~TempCtrl()
{
disconnectDevice();
}
TempCtrl* TempCtrl::instance()
{
static TempCtrl* theInstance = new TempCtrl();
return theInstance;
}
bool TempCtrl::connectDevice()
{
disconnectDevice();
const auto serialPortInfos = QSerialPortInfo::availablePorts();
if(!serialPortInfos.empty())
{
QModbusRequest echoTest(QModbusRequest::Diagnostics, quint16(0x0000), quint16(0x1234));
bool comportFound(false);
for (const QSerialPortInfo &serialPortInfo : serialPortInfos)
{
m_modbusDevice.setConnectionParameter(QModbusDevice::SerialPortNameParameter, serialPortInfo.portName());
if(m_modbusDevice.connectDevice())
{
auto curTimePt = std::chrono::steady_clock::now();
double duration = 0;
while(m_modbusDevice.state() != QModbusDevice::ConnectedState && duration < 2.0)
{
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 20);
std::chrono::duration<double> d = std::chrono::steady_clock::now()-curTimePt;
duration = d.count();
}
if(m_modbusDevice.state() == QModbusDevice::ConnectedState)
{
try
{
QModbusResponse reply = sendModbusRawRequest(echoTest);
if(reply.isValid())
{
if(reply.data() == QByteArray::fromHex("00001234"))
{
if(!comportFound)
{
comportFound = true;
}
m_channelConnected = true;
}
}
}
catch(...)
{
}
}
if(comportFound)
{
break;
}
else
{
m_modbusDevice.disconnectDevice();
}
}
}
}
m_modbusDevice.setTimeout(500);
m_modbusDevice.setNumberOfRetries(3);
return m_channelConnected;
}
void TempCtrl::disconnectDevice()
{
if(m_modbusDevice.state() != QModbusDevice::UnconnectedState)
{
m_modbusDevice.disconnectDevice();
}
m_channelConnected = false;
}
QModbusResponse TempCtrl::sendModbusRawRequest(const QModbusRequest &request) const
{
QModbusReply* reply = m_modbusDevice.sendRawRequest(request, m_channelAddr);
if(reply)
{
while(!reply->isFinished())
{
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 20);
}
reply->deleteLater();
if(reply->error() == QModbusDevice::NoError)
{
auto response = reply->rawResult();
std::this_thread::sleep_for(std::chrono::milliseconds(5));
return response;
}
else if (reply->error() == QModbusDevice::ProtocolError)
{
QString error = "Protocol error: " + reply->errorString();
throw std::exception(error.toStdString().c_str());
}
else if (reply->error() == QModbusDevice::TimeoutError)
{
throw std::exception("Timeout error");
}
else
{
throw std::exception("Unknown error");
}
}
else
{
return QModbusResponse();
}
}