qt实现串口检测热拔插
时间: 2023-10-23 20:12:05 浏览: 87
要实现串口的热插拔检测,需要通过操作系统提供的API来实现。
在Windows操作系统下,可以使用以下API来实现串口的热插拔检测:
1. 使用RegisterDeviceNotification函数注册串口设备的通知。这个函数可以让Windows操作系统在串口设备的状态发生改变时向应用程序发送通知消息。
2. 在应用程序中处理Windows发送的串口设备通知消息,根据消息的内容来判断串口设备的状态是否发生了改变。
3. 如果串口设备的状态发生了改变,可以在应用程序中重新打开或关闭串口设备。
下面是一个简单的Qt程序,演示了如何实现串口的热插拔检测:
```cpp
#include <QtCore/QCoreApplication>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <Windows.h>
class SerialPortWatcher : public QObject
{
Q_OBJECT
public:
SerialPortWatcher(QObject *parent = nullptr)
: QObject(parent)
{
// 注册串口设备的通知
DEV_BROADCAST_DEVICEINTERFACE dbi;
ZeroMemory(&dbi, sizeof(dbi));
dbi.dbcc_size = sizeof(dbi);
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
HDEVNOTIFY hDevNotify = RegisterDeviceNotification((HANDLE)winId(), &dbi, DEVICE_NOTIFY_WINDOW_HANDLE);
if (hDevNotify == nullptr) {
qWarning() << "Failed to register device notification: " << GetLastError();
}
}
signals:
void serialPortChanged();
protected:
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override
{
// 处理串口设备通知消息
MSG *msg = static_cast<MSG *>(message);
if (msg->message == WM_DEVICECHANGE) {
switch (msg->wParam) {
case DBT_DEVICEARRIVAL:
case DBT_DEVICEREMOVECOMPLETE:
emit serialPortChanged();
break;
}
}
return QObject::nativeEvent(eventType, message, result);
}
};
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
SerialPortWatcher watcher;
QSerialPort serialPort;
// 串口状态改变处理函数
auto handleSerialPortChanged = [&] {
QList<QSerialPortInfo> infos = QSerialPortInfo::availablePorts();
if (infos.isEmpty()) {
qDebug() << "No serial port available";
if (serialPort.isOpen()) {
serialPort.close();
}
} else {
QSerialPortInfo info = infos.first();
if (serialPort.portName() != info.portName()) {
qDebug() << "Serial port changed to: " << info.portName();
if (serialPort.isOpen()) {
serialPort.close();
}
serialPort.setPort(info);
serialPort.setBaudRate(QSerialPort::Baud115200);
serialPort.setDataBits(QSerialPort::Data8);
serialPort.setParity(QSerialPort::NoParity);
serialPort.setStopBits(QSerialPort::OneStop);
serialPort.setFlowControl(QSerialPort::NoFlowControl);
if (!serialPort.open(QIODevice::ReadWrite)) {
qDebug() << "Failed to open serial port: " << serialPort.errorString();
}
}
}
};
QObject::connect(&watcher, &SerialPortWatcher::serialPortChanged, handleSerialPortChanged);
handleSerialPortChanged();
return app.exec();
}
#include "main.moc"
```
这个程序使用了QtSerialPort模块提供的QSerialPort和QSerialPortInfo类来操作串口设备,使用Windows API来实现串口设备的热插拔检测。
在程序中,SerialPortWatcher类继承自QObject类,重载了nativeEvent函数来处理Windows发送的消息。在构造函数中,调用了RegisterDeviceNotification函数来注册串口设备的通知。在nativeEvent函数中,判断接收到的消息是否为串口设备通知消息,如果是则发送serialPortChanged信号。
程序的主函数中,创建了一个SerialPortWatcher对象和一个QSerialPort对象。使用lambda表达式来定义串口状态改变处理函数,将serialPortChanged信号和处理函数连接起来。然后调用handleSerialPortChanged函数来初始化串口设备。在程序运行期间,如果串口设备的状态发生了改变,程序会重新打开或关闭串口设备。
需要注意的是,这个程序只是一个演示程序,还有一些细节问题需要考虑,比如使用QThread来将串口操作放在单独的线程中,使用QTimer来定时检测串口设备的状态等等。
阅读全文