Qt 之 Modbus通信(RTU模式)

相关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();
    }
}
发布了9 篇原创文章 · 获赞 3 · 访问量 896

猜你喜欢

转载自blog.csdn.net/qq_23516957/article/details/103821423