ESM6802使用iMX6DL作為CPU,支持硬件圖形加速,使得用戶可以開發具有較好圖形界面的工業控制程序。Qt是嵌入式開發中常用的圖形庫,MODBUS作為工控中常用的通信協議,已經作為Qt的模塊引入了Qt中。我們在ESM6802上移植了最新的Qt 5.8.0版本,包括MODBUS模塊,用戶在使用中可以方便的調用Qt提供的API進行MODBUS協議相關的程序編寫。Qt對于MODBUS協議的封裝使得用戶能夠更加便捷快速的進行MODBUS應用程序開發,我們將在下面根據Qt源碼中的modbusmaster例程簡單介紹Qt的MODBUS相關函數接口。文中使用的程序可以在http://doc.qt.io/qt-5/qtserialbus-modbus-master-example.html獲取或向我們的工程師索取。
在使用Qt提供的MODBUS相關API時需要使用Qt提供的MODBUS數據類:QModbusDataUnit,類中有公共數據RegisterType表示此數據代表的MODBUS數據類型:
enum RegisterType { Invalid, DiscreteInputs, Coils, InputRegisters, HoldingRegisters }
可以使用構造函數進行初始化:
QModbusDataUnit(RegisterType type, int address, quint16 size)
對于MODBUS client相關的函數,Qt將其封裝在類QModbusClient中,部分函數如下:
int numberOfRetries() const
QModbusReply * sendRawRequest(const QModbusRequest &request, int serverAddress)
QModbusReply * sendReadRequest(const QModbusDataUnit &read, int serverAddress)
QModbusReply * sendReadWriteRequest(const QModbusDataUnit &read, const QModbusDataUnit &write, int serverAddress)
QModbusReply * sendWriteRequest(const QModbusDataUnit &write, int serverAddress)
void setNumberOfRetries(int number)
void setTimeout(int newTimeout)
int timeout() const
其中numberOfRetries以及setTimeout是用于設置重試次數和超時時間的。send*Request系列函數是用于發送MODBUS數據包的函數,其中數據相關的都用之前介紹的QModbusDataUnit類對象作為函數參數。
截取部分Qt例程modbusmaster發送讀請求的代碼如下:
首先設置連接類型(RTU/TCP)、重試次數、超時時間等,然后建立連接:
if (static_cast<ModbusConnection> (ui->connectType->currentIndex()) == Serial) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
ui->portEdit->text());
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
m_settingsDialog->settings().parity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
m_settingsDialog->settings().baud);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
m_settingsDialog->settings().dataBits);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
m_settingsDialog->settings().stopBits);
} else {
const QUrl url = QUrl::fromUserInput(ui->portEdit->text());
modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, url.port());
modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, url.host());
}
modbusDevice->setTimeout(m_settingsDialog->settings().responseTime);
modbusDevice->setNumberOfRetries(m_settingsDialog->settings().numberOfRetries);
if (!modbusDevice->connectDevice()) {
statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
}
設置讀取數據類型、地址等參數:
QModbusDataUnit MainWindow::readRequest() const
{
const auto table =
static_cast<QModbusDataUnit::RegisterType> (ui->writeTable->currentData().toInt());
int startAddress = ui->readAddress->value();
Q_ASSERT(startAddress >= 0 && startAddress < 65535);
// do not go beyond 10 entries
int numberOfEntries = qMin(ui->readSize->currentText().toInt(), 65535 - startAddress);
return QModbusDataUnit(table, startAddress, numberOfEntries);
}
發送讀數據請求:
void MainWindow::on_readButton_clicked()
{
if (!modbusDevice)
return;
ui->readValue->clear();
statusBar()->clearMessage();
if (auto *reply = modbusDevice->sendReadRequest(readRequest(), ui->serverEdit->value())) {
if (!reply->isFinished())
connect(reply, &QModbusReply::finished, this, &MainWindow::readReady);
else
delete reply; // broadcast replies return immediately
} else {
statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000);
}
}
可以看到使用Qt提供的API進行MODBUS通訊編程很便捷,只需要首先設置數據QModbusDataUnit,然后調用相應的Request函數發送請求即可。
modbusmaster程序運行效果如下圖:
我們使用ESM6802連接ADAM模塊進行測試連接圖如下:
ADAM-4117進行電流采集時電流輸入量程為4~20mA,對應的采樣值為0x0000~0xffff。有關AMAM-4117的介紹可以參考我們官網上的文章:《4~20mA模擬電流采集應用方案》。當輸入12.0mA(半量程)時讀到采樣值為0x8007,可見modbusmaster與AMAM模塊正確進行了數據通信。
更多Qt MODBUS相關內容請參考Qt官方資料:http://doc.qt.io/qt-5/qtmodbus-backends.html。
成都英創信息技術有限公司 028-8618 0660