1.使用USB转串口测试了一下上位机中Modbus协议那部分程序,上位机机与下位机不能通信,不能下发数据,也不能读取数据。主机执行connectDevice()函数后,
APF_ModbusData->ModbusMaster->state() == QModbusDevice::ConnectedState成立,执行sendReadRequest()后,返回的指针对象调用error()函数后也没有错误。按理说state()返回值等于
QModbusDevice::ConnectedState表示Modbus网络应该已经连接上了,而且error()返回值也没错,但是为什么不能下发数据和读取数据呢?程序能正常执行,但是读取数据时,发送请求和读取数都不成功。
下面是我的代码,看Modbus线程中遥测部分的程序即可
2.Modbus处理数据的线程程序
#include "ModbusDataThread.h"
#include "GUIDataThread.h"
#include
#include
无
int DataMode = 2; //数据处理模式选择 1.遥调;2.遥测;3.遥信;
extern QMutex Mutex;
void ModbusDataThread::run()
{
APF_ModbusData = new ModbusData;
while(true)
{
if( APF_ModbusData->ModbusMaster->state() != QModbusDevice::ConnectedState)
{
int state1 = APF_ModbusData->ModbusMaster->state();
qDebug() << "state1" << state1;
APF_ModbusData->Modbus_Connection();
msleep(2000);
}
if( APF_ModbusData->ModbusMaster->state() == QModbusDevice::ConnectedState )
{
int state3 = APF_ModbusData->ModbusMaster->state();
qDebug() << "state3" << state3;
qDebug() << "通信成功";
while(true)
{
if( DataMode == 1 ) //Modbus处理遥调数据
{
Mutex.lock();
APF_ModbusData->RemoAdjust_DataTrans_Modbus();
APF_ModbusData->Modbus_ReadWriteDatas_RemoAdjust(1);
RemoAdjust_GUI = RemoAdjust_Modbus;
//qDebug() << RemoAdjust_GUI;
DataMode = 2;
Mutex.unlock();
msleep(2000);
}
if( DataMode == 2 ) //Modbus处理遥测数据
{
Mutex.lock();
qDebug() << "遥测";
APF_ModbusData->Modbus_ReadDatas_RemoMea(1);
RemoMea_GUI = RemoMea_Modbus;
DataMode = 3;
Mutex.unlock();
msleep(2000);
}
if( DataMode == 3 ) //Modbus处理遥信数据
{
Mutex.lock();
qDebug() << "Modbus";
qDebug() << "遥信";
APF_ModbusData->Modbus_ReadDatas_RemoSignal(1);
RemoSignal_GUI = RemoSignal_Modbus;
DataMode = 2;
Mutex.unlock();
msleep(2000);
}
}
}
}
delete APF_ModbusData->ModbusMaster;
}
3.设置串口参数和连接程序APF_ModbusData->Modbus_Connection();
void ModbusData::Modbus_Connection()
{
if (!ModbusMaster)
return;
QString portname = "/dev/ttyUSB0";
ModbusMaster->setConnectionParameter(QModbusDevice::SerialPortNameParameter,portname);
ModbusMaster->setConnectionParameter(QModbusDevice::SerialParityParameter,QSerialPort::NoParity);
ModbusMaster->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,QSerialPort::Baud9600);
ModbusMaster->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,QSerialPort::Data8);
ModbusMaster->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,QSerialPort::OneStop);
ModbusMaster->setTimeout(1000);
ModbusMaster->setNumberOfRetries(3);
ModbusMaster->connectDevice();
}
4.APF_ModbusData->Modbus_ReadDatas_RemoMea() ,此为遥测发送请求和读取数据的函数
void ModbusData::Modbus_ReadDatas_RemoMea(int serverAddress)
{
if (!ModbusMaster)
return;
QModbusDataUnit readRequest_RemoMea(QModbusDataUnit::InputRegisters,1,100);
if ( auto *Reply = ModbusMaster->sendReadRequest( readRequest_RemoMea, serverAddress))
{
quint16 error_RemoMea = Reply->error();
qDebug() << "error_RemoMea" << error_RemoMea;
if ( !Reply->isFinished() )
{
bool a = connect(Reply, &QModbusReply::finished, this, &ModbusData:: ReadReady_RemoMea);
qDebug() << a;
}
else
{
delete Reply;
}
}
else
{
qDebug() << "request error";
}
}
5.插槽函数ReadReady_RemoMea()为函数Modbus_ReadDatas_RemoMea()中
connect(Reply, &QModbusReply::finished, this, &ModbusData:: ReadReady_RemoMea);关联的插槽函数。
void ModbusData::ReadReady_RemoMea()
{
QModbusReply *reply = qobject_cast(sender());
if (!reply)
return;
if (reply->error() == QModbusDevice::NoError)
{
RemoMea_Modbus = reply->result().values(); //返回读取的遥测数据
}
else
{
qDebug() << "reply error";
}
reply->deleteLater(); //delete the reply
}