欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:Qt 使用modbus協(xié)議

柚子快報激活碼778899分享:Qt 使用modbus協(xié)議

http://yzkb.51969.com/

Qt 框架下 使用modbus協(xié)議

一,使用Qt原生的 QModbusClient ,比如QModbusTcpClient

1,因為modbus的讀寫 需要在同一個線程中,所以需要在主線程中利用moveToThread的方式,將業(yè)務(wù)邏輯封裝到 子線程中。

2,modbus封裝

#pragma once

#include

#include

#include

#include

namespace Device {

class Modbus:public QObject{

Q_OBJECT

public:

Modbus(QObject*parent): QObject(parent){

}

protected:

bool modbusRead(QModbusTcpClient * modbusMaster,int serverAddress, QModbusDataUnit::RegisterType type, int newStartAddress, quint16 newValueCount, QList &array, bool warning){

QModbusDataUnit readUnit(type, newStartAddress, newValueCount);

QModbusReply *reply = modbusMaster->sendReadRequest(readUnit, serverAddress);

if(reply == nullptr)

{

qDebug()<

return false;

}

while (!reply->isFinished())

{

QCoreApplication::processEvents();

}

if (reply->error() == QModbusDevice::NoError)

{

QModbusDataUnit resultUnit = reply->result();

for (int i = 0; i < static_cast(resultUnit.valueCount()); ++i) {

array.append(resultUnit.value(i));

}

return true;

}

else

{

qDebug()<errorString());

return false;

}

}

bool modbusWrite(QModbusTcpClient * modbusMaster,int serverAddress, QModbusDataUnit::RegisterType type, int newStartAddress, quint16 newValueCount, QList array, bool warning){

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()<

return false;

}

while (!reply->isFinished())

{

QCoreApplication::processEvents();

}

if (reply->error() == QModbusDevice::NoError)

{

return true;

}

else

{

qDebug()<errorString());

return false;

}

}

};

}

3,繼承上述類,封裝業(yè)務(wù)邏輯,以壓力傳感器為例。將功能放到槽函數(shù)中。

class ModbusWorkerPressure:public Modbus{

Q_OBJECT

public:

explicit ModbusWorkerPressure(Modbus*parent= nullptr);

~ModbusWorkerPressure() override;

public slots:

void open();

void close();

void zero();

signals:

void siStatus(int type,int result);

private:

QModbusTcpClient *modbusClient{nullptr};

bool bOpened{false};

bool bExit{false};

};

ModbusWorkerPressure::ModbusWorkerPressure(Modbus *parent): Modbus(parent) {

}

ModbusWorkerPressure::~ModbusWorkerPressure() {

}

void ModbusWorkerPressure::close() {

bExit = true;

DELAY(500);

if (bOpened) {

modbusClient->disconnectDevice();

}

if (modbusClient != nullptr) {

modbusClient->deleteLater();

}

}

void ModbusWorkerPressure::open() {

modbusClient = new QModbusTcpClient(this);

modbusClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "10.10.10.2");

modbusClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);

modbusClient->setTimeout(500);

if (modbusClient->connectDevice()) {

DELAY(500);

while (!bExit) {

QList list;

int32_t pressure=0;

if(modbusRead(modbusClient,1,QModbusDataUnit::HoldingRegisters,0x0000,0x0002,list,false)){

int result = 0;

result =static_cast(list[1])<<16|list[0];

pressure = result;

//單位g

DataManager::Instance().setCurPressure(pressure);

//能讀出數(shù)據(jù) 認(rèn)為連接成功

static bool execute = false;

if (!execute) {

bOpened = true;

emit siStatus(0, 0);

execute = true;

}

}

DELAY(5);

}

} else {

emit siStatus(0, -1);

bOpened = false;

}

}

void ModbusWorkerPressure::zero() {

QList list{0x0001};

if (!modbusWrite(modbusClient,1, QModbusDataUnit::HoldingRegisters, 0x0002, 0x0001, list, false)) {

LOGE(u8"壓力傳感器 清零失敗!");

}

}

4, 主線程 使用moveToThread 將上述業(yè)務(wù)線程進(jìn)行封裝,然后主線程中 用信號,進(jìn)行觸發(fā)

bool PressureSensor::open()

{

workerThread = new QThread();

modbusWorker = new ModbusWorkerPressure();

modbusWorker->moveToThread(workerThread);

QObject::connect(workerThread, &QThread::started, modbusWorker, &ModbusWorkerPressure::open);

QObject::connect(this, &PressureSensor::siClose, modbusWorker, &ModbusWorkerPressure::close);

QObject::connect(this, &PressureSensor::siZero, modbusWorker, &ModbusWorkerPressure::zero);

QObject::connect(modbusWorker, &ModbusWorkerPressure::siStatus, [&](int type, int result) {

if (type == 0) {

if (result == 0) {

bOpened = true;

} else {

bOpened = false;

}

}

});

workerThread->start();

return true;

}

bool PressureSensor::zero() {

if(!bOpened)

return false;

emit siZero();

return true;

}

5,此種方式 優(yōu)點(diǎn)就是Qt原生框架,但是缺點(diǎn)是 這種方式是異步的方式,想要做到同步調(diào)用,比如軸系運(yùn)動中,需要自己去同步,試過 QEventLoop的方式,但是不行,會丟失事件。

二,第三方庫 libmodbus

1,編譯及下載

Libmodbus在win11下的編譯與VS2019下的運(yùn)行_libmodbus vs2019-CSDN博客

2,寫bool

auto home = [&](bool flag){

const int read_regAddress = 55;

const int numBits = 1;

uint16_t coilStatus[numBits];

int rc;

{

QMutexLocker locker(&mutex);

rc = modbus_read_registers(modbusContext,read_regAddress,numBits,coilStatus);

}

if (rc == -1) {

LOGE(QString("goHome Failed to read Modbus coils %1").arg(modbus_strerror(errno)).toUtf8());

}

else {

uint16_t value = coilStatus[0];

if(flag){

value|=0x80;

}else{

value&=0xFF7F;

}

{

QMutexLocker locker(&mutex);

rc = modbus_write_register(modbusContext, read_regAddress, value);

}

if (rc == -1) {

LOGE(QString("goHome Failed to write Modbus coil %1").arg(modbus_strerror(errno)).toUtf8());

}

}

};

home(false);

DELAY(100);

home(true);

3,讀取double

while (!bExit){

const int read_regAddress = 1104;

const int numBits = 4;

uint16_t coilStatus[numBits];

int rc;

{

QMutexLocker locker(&mutex);

rc = modbus_read_registers(modbusContext,read_regAddress,numBits,coilStatus);

}

if (rc == -1) {

LOGE(QString("getPos Failed to read Modbus coils %1").arg(modbus_strerror(errno)).toUtf8());

}

else {

::uint64_t combined = static_cast(coilStatus[3]) << 48 |static_cast(coilStatus[2]) << 32|static_cast(coilStatus[1]) << 16| coilStatus[0];

double realValue;

std::memcpy(&realValue, &combined, sizeof(realValue));

DataManager::Instance().setCurZ(realValue*1000);

}

DELAY(5);

}

4,寫double

//位置

const int write_regAddress_pos = 1150;

const int numReg = 4;

::uint64_t rawPos = *reinterpret_cast<::uint64_t*>(&ptpPos);

::uint16_t listPos[4]{static_cast(rawPos&0xFFFF),static_cast((rawPos>>16)&0xFFFF),static_cast((rawPos>>32)&0xFFFF),static_cast((rawPos>>48)&0xFFFF)};

int rc;

{

QMutexLocker locker(&mutex);

rc = modbus_write_registers(modbusContext, write_regAddress_pos,numReg, listPos);

}

if (rc == -1) {

LOGE(QString("setPos Failed to write Modbus coil %1").arg(modbus_strerror(errno)).toUtf8());

}

5,注意

modbus_t 并不是線程安全的,因此在使用的地方 需要加鎖。親測這個 比Qt原生的好用

柚子快報激活碼778899分享:Qt 使用modbus協(xié)議

http://yzkb.51969.com/

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/2027313653.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄