記事ディレクトリ
1. 例
2. コンピュータのシリアルデバイスをポーリングする
// 查询所有串口设备
QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();
QStringList serialPortNameList;
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
serialPortNameList << info.portName();
qDebug()<<"serialPortName: "<<info.portName();
}
// 展示在下拉列表中
ui->comboBox->addItems(serialPortNameList);
QSerialPort を使用するには、pro に追加する必要があることに注意してください。QT += serialport
3. シリアルクラス
m_serialPort = new QSerialPort(this);
connect(m_serialPort, &QSerialPort::readyRead, this, &MainWindow::handleReadyRead);
connect(m_serialPort, &QSerialPort::errorOccurred, this, &MainWindow::handleError);
readRead 事件
:シリアルデータを非同期で受信中
errorOccurred 事件
:異常
void MainWindow::handleReadyRead()
{
m_recvData = m_serialPort->readAll();
writeMsg("异步收到:" + QString::fromUtf8(m_recvData));
emit serialDataReadFinished(); // 自定义的事件,为了配合通知异步等待完成
}
void MainWindow::handleError(QSerialPort::SerialPortError serialPortError)
{
if (serialPortError == QSerialPort::ReadError)
{
QString error = QString("An I/O error occurred while reading "
"the data from port %1, error: %2")
.arg(m_serialPort->portName())
.arg(m_serialPort->errorString());
writeMsg(error);
}
}
4. シリアルデータの送信
4.1 シリアルポートデータ送信後は待たずにhandleReadyRead
シリアルポートから非同期でデータを受信する
void MainWindow::on_sendMsgButton_clicked()
{
QString sendData = ui->textEdit->toPlainText();
writeMsg("发送:" + sendData);
m_serialPort->write(sendData.toUtf8(), sendData.toUtf8().size());
}
4.2 シリアル ポート データを送信した後、シリアル ポートがデータを同期して返すのを待ちます。
void MainWindow::on_sendMsgButton_clicked()
{
QString sendData = ui->textEdit->toPlainText();
writeMsg("发送:" + sendData);
m_serialPort->write(sendData.toUtf8(), sendData.toUtf8().size());
if(!m_serialPort->waitForReadyRead(5000))
{
writeMsg("等待回复超时");
return;
}
QByteArray recvData = m_serialPort->readAll();
writeMsg("同步收到:" + QString::fromUtf8(recvData));
}
QSerialPort
ただし、イベントをリッスンするとreadRead
、waitForReadyRead
シリアル ポートから返されるデータを待つことができず、常にタイムアウトになります。
場合によっては、シリアル ポートにメッセージを送信した後、シリアル ポートから返されたデータを時間内に受信する必要があり、また、メッセージが送信されていないときに、非同期監視を使用してシリアル ポートから報告されたデータをリアルタイムで受信する必要もあります。
したがって:
a. シリアル ポート データの同期読み取りを待機する必要がある; b.イベントを監視し、リアルタイムでデータを受信する
必要があるreadRead
解決策 1:
非同期待機メソッドを自分で記述して、非同期を同期にすることができます
bool MainWindow::waiteForReadyRead(int msec)
{
QEventLoop eventloop;
QObject::connect(this, &MainWindow::serialDataReadFinished, &eventloop, &QEventLoop::quit);
bool isTimeout = false;
QTimer::singleShot(msec, &eventloop, [&](){
eventloop.quit();
isTimeout = true;
});
eventloop.exec(QEventLoop::AllEvents);
return !isTimeout;
}
serialDataReadFinished
このイベントはカスタム イベントで、シリアル ポート データが handleReadyRead スロット関数で受信された後、このイベントは非同期待機の終了を通知するために送信されます。QTimer::singleShot
タイミングとしては、タイムアウト後に非同期待機も終了します。- 戻り値は、
serialDataReadFinished
受信イベントの終了待ちの非同期の場合は正常終了でtrueを返し、タイムアウト終了の場合は異常終了でfalseを返します。
したがって、シリアル ポート データを送信した後、結果を待つ必要がある場合は、次のように記述できます。
void MainWindow::on_sendMsgButton_2_clicked()
{
QString sendData = ui->textEdit->toPlainText();
writeMsg("发送:" + sendData);
m_serialPort->write(sendData.toUtf8(), sendData.toUtf8().size());
if(!waiteForReadyRead(5000)) // 自定义的异步等待函数
{
writeMsg("等待回复超时");
}
else
{
writeMsg("同步收到: " + m_recvData);
}
}
解決策 2:
write
切断イベントが切断される前にreadRead
、シリアル ポート クラスに付属する waitForReadyRead を使用してシリアル ポート データを待ってから、シリアル ポート データを読み取ります。読み込み後は再度connectreadRead
イベントを使用してください。
void MainWindow::on_sendMsgButton_2_clicked()
{
QString sendData = ui->textEdit->toPlainText();
writeMsg("发送:" + sendData);
// 断开readyRead事件
disconnect(m_serialPort, &QSerialPort::readyRead, this, &MainWindow::handleReadyRead);
m_serialPort->write(sendData.toUtf8(), sendData.toUtf8().size());
if(!m_serialPort->waitForReadyRead(5000)) // 串口类自带的等待函数
{
writeMsg("等待回复超时");
}
else
{
m_recvData = m_serialPort->readAll();
writeMsg("同步收到: " + m_recvData);
}
// 重新连接readyRead事件
connect(m_serialPort, &QSerialPort::readyRead, this, &MainWindow::handleReadyRead);
}
上記の完全なコード: QSerialPortTest
5. テスト
仮想シリアル ポート ツールの仮想シリアル ポートをダウンロードし、仮想シリアル ポート ペアを作成します。たとえば、私が作成したシリアル ポート ペアは COM4 と COM5 です。
シリアル ポート ペアを作成した後、システム デバイス マネージャーで次のように表示されます。
テスト プログラムをコンパイルした後、COM4 用と COM5 用の 2 つのプロセスを開きます。