此文章不赘述基础理论
1. pro文件
QT += serialbus
2 .H
添加头文件
#include <QModbusRtuSerialMaster>
3.Cpp
QModbusRtuSerialMaster *modbusMaster;
modbusMaster = new QModbusRtuSerialMaster;
// modbusMaster->setConnectionParameter(QModbusDevice::SerialPortNameParameter, "COM1");
modbusMaster->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);//奇偶校验
modbusMaster->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud115200);
modbusMaster->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
modbusMaster->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
modbusMaster->setTimeout(30);//等待回应时间
函数setTimeout函数介绍
void QModbusClient::setTimeout(int newTimeout)
Sets the newTimeout for this QModbusClient instance. The minimum timeout is 10 ms.
The timeout is used by the client to determine how long it waits for a response from the server. If the response is not received within the required timeout, the TimeoutError is set.
Already active/running timeouts are not affected by such timeout duration changes.
Note: Setter function for property timeout.
See also timeout and timeoutChanged().
打开串口(自行删除闲于代码)
//打开串口
if(modbusMaster->state() != QModbusDevice::ConnectedState)
{
if(!modbusMaster->connectDevice())
{
qDebug() << "串口打开失败";
Custom_warning::Display("串口打开失败!", Custom_warning::OK);
}
else
{
//判断是否连接有用 01 03 9C 40 00 0A EA 49
QList<quint16> data;
if(!Modbus_Read(modbus_rtc_parameter.slave_address, QModbusDataUnit::InputRegisters,
SYSTEM_DISPLAY_REGISTER_ADDRESSS, 1, data, 0))
{
Custom_warning::Display("对接失败,请检查串口和设备地址是否正确", Custom_warning::OK);
modbusMaster->disconnectDevice();//关闭串口
return;
}
Pushbutton_State_Enabel("打开");
//打开modbus读取
timer1->start();
//打开成功记录一下串口名字
software_flag.user_habit_portname = ui->comboBox_port_name->currentText();
emit Control_State(true);
}
}
else
{
timer1->stop();
modbusMaster->disconnectDevice();
Pushbutton_State_Enabel("关闭");
software_flag.communication_state = "空闲";
emit Control_State(false);
}
关闭串口
//关闭modbus串口
if(modbusMaster->state() != QModbusDevice::UnconnectedState)
{
modbusMaster->disconnectDevice();
}
读取函数
下面所有函数Custom_warning::Display都是我自定义的提示框,你们可以改变为QMessageBox就可以。
读取实例
QList<quint16> data;
data.clear();
#define LD_CURRENT_REGISTER_LEN (20)//读取长度
#define LD_CURRENT_REGISTER_ADDRESSS (40400)//读取地址
if(Modbus_Read(modbus_rtc_parameter.slave_address, QModbusDataUnit::HoldingRegisters,
SEEP_PULSE_WIDTH_REGISTER_ADDRESSS, SEEP_PULSE_WIDTH_REGISTER_LEN, data, true))
{
//读取成功
}
/**
* @brief 读取modbus
* @param serverAddress,:丛机地址
* @param type:读取的寄存器类型,QModbusDataUnit::InputRegisters
* @param newStartAddress:读取寄存器的起始地址
* @param newValueCount:要读取的寄存器个数
* @param array:读取的数组
* @param warning:报警开关
* @retval 成功true,失败false
*/
bool Modbus_Read(int serverAddress, QModbusDataUnit::RegisterType type, int newStartAddress, quint16 newValueCount, QList<quint16> &array, bool warning)
{
//保持寄存器,起始地址为0,读取的寄存器数量为1。
QModbusDataUnit readUnit(type, newStartAddress, newValueCount);
//发送读取请求并将请求的结果保存在reply指针中,最后面是地址
QModbusReply *reply = modbusMaster->sendReadRequest(readUnit, serverAddress);
if(reply == nullptr)
{
qDebug() << "客户端发出无效请求";
return false;
}
//应答没有终止,就一直等待,终止返回true
while (!reply->isFinished())
{
QCoreApplication::processEvents();
}
//检查是否有错误码
if (reply->error() == QModbusDevice::NoError)
{
QModbusDataUnit resultUnit = reply->result();
for (int i = 0; i < static_cast<int>(resultUnit.valueCount()); ++i)
array.append(resultUnit.value(i));
return true;
}
else
{
qDebug()<< "reply " << reply->errorString() << "寄存器:" << newValueCount << newStartAddress;//打印错误码状态
if(warning)
Custom_warning::Display("数据读取失败", Custom_warning::OK);
return false;
}
}
写入函数
写入实例
if(Modbus_Read(modbus_rtc_parameter.slave_address, QModbusDataUnit::HoldingRegisters,
40005, 1, data, 1))
{
//写入成功后函数
}
/**
* @brief 写入modbus
* @param serverAddress,:丛机地址
* @param type:写入寄存器类型,QModbusDataUnit::InputRegisters
* @param newStartAddress:写入寄存器的起始地址
* @param newValueCount:要写入的寄存器个数
* @param array:写入的数组
* @param warning:报警开关
* @retval 成功true,失败false
*/
bool Modbus_Write(int serverAddress, QModbusDataUnit::RegisterType type, int newStartAddress, quint16 newValueCount, QList<quint16> array, bool warning)
{
static int count = 0;
QModbusDataUnit writeUnit(type, newStartAddress, newValueCount);
for(int i = 0; i < newValueCount; i++)
writeUnit.setValue(i, array.value(i));
QModbusReply *reply = modbusMaster->sendWriteRequest(writeUnit, serverAddress);
if(reply == nullptr)
{
qDebug() << "客户端发出无效请求";
if(warning)
Custom_warning::Display("数据写入失败", Custom_warning::OK);
return false;
}
while (!reply->isFinished())
{
QCoreApplication::processEvents();
}
if (reply->error() == QModbusDevice::NoError)
{
qDebug()<< count++ << " 写入成功";
return true;
}
else
{
qDebug()<< count++ << "写入失败reply " + reply->errorString();
if(warning)
Custom_warning::Display("数据写入失败", Custom_warning::OK);
}
return false;
}
3.3打印
/**
* @brief 十进制字符串打印
* @param datat 数据
* @param type quint16,数据类型
*/
QString Decimal_Printing(QList<quint16> datat, QString type)
{
QString str = "str ";
str.append(QString::number(datat.length()) + " = ");
for(int i = 0; i < datat.length(); i++)
{
if(type == "quint16")
str.append(QString::number(datat.value(i)) + " ");
else if(type == "qint16")
str.append(QString::number(static_cast<qint16>(datat.value(i))) + " ");
}
return str;
}
/**
* @brief 十六进制字符串打印
*/
QString Hex_Printing(QList<quint16> datat)
{
uint8_t array_data[datat.length() * 2];
uint8_t temp = 0;
int count = 0;
for(int i = 0; i < datat.length() * 2; i+=2)
{
array_data[i] = (datat.value(count) & 0xFF);
array_data[i+1] = ((datat.value(count) >> 8) & 0xFF);
count++;
}
for(int i = 0; i < datat.length() * 2; i+=2)
{
temp = 0;
temp = array_data[i];
array_data[i] = array_data[i+1];
array_data[i+1] = temp;
}
QByteArray byte;
byte.resize(datat.length() * 2);
for(int i = 0; i < datat.length() * 2; i++)
byte[i] = array_data[i];
QString ret = "HEX ";
ret.append(QString::number(datat.length() * 2) + " = ");
for(int i = 0; i < byte.count(); i++)
ret.append(QString("%1 ").arg((uchar)byte.at(i), 2, 16, (QChar)'0'));
return ret.toUpper();
}
modbus通讯数据保存参数QT Modbus通讯数据获取-CSDN博客