|
- /***********************************************************************
- * Copyright (C) 2025-, XINJE Co., Ltd.
- *
- * File Name: modbus_master.h
- * Description: Modbus主站的ModbusRTUMaster头文件,主要负责四种请求帧的生成:(01)(03)(0F)(10)、响应帧的解析。
- * Others:
- * Version: v1.0
- * Author: weikai XINJE
- * Date: 2025-7-30
- ***********************************************************************/
-
-
-
- #ifndef MODBUS_RTU_MASTER_H
- #define MODBUS_RTU_MASTER_H
-
- #include <QObject>
- #include <QByteArray>
- #include <QVector>
- #include <QHash>
-
- const int TYPE_REGISTERS = 1;
- const int TYPE_COILS = 2;
-
- /**********************************************************************
- * Iterates over the contents of a ModbusRTUMaster.
- *ModbusRTUMaster:
- *提供Modbus RTU协议的主站功能,支持生成各种Modbus RTU请求帧,
- *以及解析从站返回的响应帧。所有协议相关参数均作为类成员变量,可通过setter方法进行设置。
- ***********************************************************************/
- class ModbusRTUMaster : public QObject
- {
- Q_OBJECT
- public:
- //构造函数
- explicit ModbusRTUMaster(QObject *parent = nullptr);
-
- //功能码枚举 - 定义Modbus协议支持的功能码
- enum FunctionCode
- {
- READ_COILS = 0x01, // 读线圈状态
- READ_HOLDING_REGISTERS = 0x03, // 读保持寄存器
- WRITE_MULTIPLE_COILS = 0x0F, // 写多个线圈
- WRITE_MULTIPLE_REGISTERS = 0x10 // 写多个保持寄存器
- };
-
- //错误码枚举 - 定义Modbus协议可能返回的错误码
- enum ErrorCode
- {
- NO_ERROR = 0x00, // 无错误
- ILLEGAL_FUNCTION = 0x01, // 非法功能 - 从站不支持该功能码
- ILLEGAL_DATA_ADDRESS = 0x02, // 非法数据地址 - 从站不支持该地址
- ILLEGAL_DATA_VALUE = 0x03, // 非法数据值 - 数据值超出范围
- SERVER_DEVICE_FAILURE = 0x04,// 从站设备故障
- ACKNOWLEDGE = 0x05, // 确认 - 请求已接收但未处理
- SERVER_DEVICE_BUSY = 0x06, // 从站设备忙 - 无法处理请求
- MEMORY_PARITY_ERROR = 0x08 // 内存奇偶性错误
- };
-
-
- //设置从站地址
- void setSlaveAddr(quint8 slaveAddr) { slaveAddr_ = slaveAddr; }
-
- //设置功能码
- void setFuncCode(FunctionCode funcCode) { funcCode_ = funcCode; }
-
- //设置起始地址
- void setStartAddr(quint16 startAddr) { startAddr_ = startAddr; }
-
- //设置读取数量
- void setReadCount(quint16 readCount) { readCount_ = readCount; }
-
- //设置线圈数据
- void setCoils(const QVector<bool>& coils) { coils_ = coils; }
-
- //设置寄存器数据
- void setRegisters(const QVector<quint16>& registers) { registers_ = registers; }
-
- //提取错误码对应描述
- QString getErrorDescription(int errorCode);
-
- //获取起始地址
- quint16 getStartAddr() const;
-
- //生成读线圈请求帧 (功能码01)
- QByteArray createReadCoilsFrame();
-
- //生成读保持寄存器请求帧 (功能码03)
- QByteArray createReadHoldingRegistersFrame();
-
- //生成写多个线圈请求帧 (功能码0F)
- QByteArray createWriteMultipleCoilsFrame();
-
- //生成写多个保持寄存器请求帧 (功能码10)
- QByteArray createWriteMultipleRegistersFrame();
-
- /***********************************************************************
- *@brief: 处理接收到的数据流并解析完整帧
- *@param: data 接收到的原始数据
- *@param: slaveAddr 输出参数,从响应中解析出的从站地址
- *@param: funcCode 输出参数,从响应中解析出的功能码
- *@param: parsedData 输出参数,解析后的数据
- *@param: errorCode 输出参数,错误码(NoError表示成功)
- *@param: extractedFrame 输出参数,提取到的完整帧
- *@return:是否成功解析
- *@note: 提取到帧后会进行解析
- ***********************************************************************/
- bool processReceivedData(const QByteArray& data, quint8& slaveAddr, quint8& funcCode,
- QVector<quint16>& parsedData, quint8& errorCode,QByteArray& extractedFrame,bool& isComFrame);
- public:
- /***********************************************************************
- *@brief: 创建读请求帧
- *@param: frame 输出参数 请求帧
- *@param: type 请求类型
- ***********************************************************************/
- void buildReadFrame(QByteArray& frame,FunctionCode funcCode);
-
- /***********************************************************************
- *@brief: 创建部分写请求帧
- *@param: frame 输出参数 请求帧
- *@param: type 请求类型
- ***********************************************************************/
- void buildWriteFrame(QByteArray& frame,FunctionCode funcCode);
-
- /***********************************************************************
- *@brief: 解析读线圈响应数据
- *@param: responseData 响应中的数据部分
- *@param: coils 输出参数(bool类型的数组),解析出的线圈状态
- *@return:是否成功解析
- ***********************************************************************/
- bool parseReadCoilsResponse(const QByteArray& responseData, QVector<bool>& coils);
-
- /***********************************************************************
- *@brief: 解析读保持寄存器响应数据
- *@param: responseData 响应中的数据部分
- *@param: registers 输出参数(quint16类型的数组),解析出的寄存器值
- *@return:是否成功解析
- ***********************************************************************/
- bool parseReadHoldingRegistersResponse(const QByteArray& responseData, QVector<quint16>& registers);
-
- /***********************************************************************
- *@brief: 解析单帧响应
- *@param: response 从站返回的响应数据
- *@param: slaveAddr 输出参数,从响应中解析出的从站地址
- *@param: funcCode 输出参数,从响应中解析出的功能码
- *@param: data 输出参数,解析后的数据
- *@param: errorCode 输出参数,错误码(NoError表示成功)
- *@return:是否成功解析
- ***********************************************************************/
- bool parseResponse(const QByteArray& response, quint8& slaveAddr, quint8& funcCode,
- QVector<quint16>& data, quint8& errorCode);
-
- /***********************************************************************
- *@brief: 从缓冲区提取完整帧
- *@param: frame 输出参数,提取的完整帧
- *@return:是否成功提取到一帧
- ***********************************************************************/
- bool extractFrame(QByteArray& frame,bool& isComFrame);
-
- //计算CRC16校验值
- quint16 calculateCRC(const QByteArray& data);
-
- //验证帧的CRC16校验
- bool verifyCRC(const QByteArray& frame);
-
- //Modbus RTU协议参数
- quint8 slaveAddr_; // 从站地址
- FunctionCode funcCode_; // 功能码
- quint16 startAddr_; // 起始地址
- quint16 readCount_; // 读取数量
- QVector<bool> coils_; // 线圈数据(写入)
- QVector<quint16> registers_; // 寄存器数据(写入)
- //其他
- QHash<int,QString> errMessage; //错误码描述映射表
- QByteArray buffer_; // 数据缓冲区
- };
-
- #endif // MODBUS_RTU_MASTER_H
|