两种串口通信方式

本文详细介绍了如何在Qt中通过QSerialPort类进行串口通信,并提供了一个使用Windows系统接口的CSerialPort类示例,展示了如何在Qt4及类似环境下进行串口操作,包括打开、读写数据和关闭串口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、通过 QT 的 QSerialPort 类

在 Qt 中进行串口通信,可以使用 QSerialPort 类。示例代码如下:

#include <QSerialPort>
#include <QSerialPortInfo>

int main() {
    QSerialPort m_serialPortObj;
    // 查找当前所有串口
    QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo& info : ports) {
        qDebug() << info.portName();
    }
    // 打开串口
    m_serialPortObj.setPortName("COM1");
    if (m_serialPortObj.open(QIODevice::ReadOnly)) {
        m_serialPortObj.setBaudRate(QSerialPort::Baud9600);
        m_serialPortObj.setDataBits(QSerialPort::Data8);
        m_serialPortObj.setParity(QSerialPort::EvenParity);
        m_serialPortObj.setStopBits(QSerialPort::OneStop);
        // 读取串口数据
        connect(&m_serialPortObj, &QSerialPort::readyRead, [&]() {
            QByteArray data = m_serialPortObj.readAll();
            qDebug() << "recv data: " << data;
        });
    } else {
        qDebug() << "Failed to open the serial port.";
    }

    // 关闭串口
    m_serialPortObj.close();
    return 0;
}

二、通过 windows 系统接口

对于 QT4 或其他无法使用 QSerialPort 类的情况,可以使用操作系统提供的串口通信 API 来实现串口通信。示例代码如下:

// 串口通信类
class CSerialPort {
   public:
    CSerialPort() : m_hSerial(INVALID_HANDLE_VALUE) {}

    ~CSerialPort() {
        CloseSerialPort();
    }

    QStringList CheckSerialPort() {
        // 获取可用串口
        QStringList portList;
        for (int i = 1; i < 256; i++) {
            QString portName = QString("COM%1").arg(i);
            HANDLE hSerial = CreateFile(
                portName.toStdWString().c_str(),
                GENERIC_READ | GENERIC_WRITE,
                0,
                nullptr,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                nullptr
            );
            if (hSerial != INVALID_HANDLE_VALUE) {
                portList.append(portName);
                CloseHandle(hSerial);
            }
        }
        return portList;
    }

    bool OpenSerialPort(const QString& portName, qint32 baudRate) {
        CloseSerialPort();
        m_hSerial = CreateFile(
            portName.toStdWString().c_str(),
            GENERIC_READ | GENERIC_WRITE,
            0,
            nullptr,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            nullptr
        );
        if (m_hSerial == INVALID_HANDLE_VALUE) {
            qDebug() << "Error opening serial port!";
            return false;
        }

        // 设置超时时间
        COMMTIMEOUTS timeouts = {0};
        timeouts.ReadIntervalTimeout = 50; // 读取数据之间的间隔超时时间(毫秒)
        timeouts.ReadTotalTimeoutConstant = 100; // 持续读取的总超时时间(毫秒)
        timeouts.ReadTotalTimeoutMultiplier = 10; // 每个字节的附加超时时间(毫秒)
        timeouts.WriteTotalTimeoutConstant = 50; // 持续写入的总超时时间(毫秒)
        timeouts.WriteTotalTimeoutMultiplier = 10; // 每个字节的附加超时时间(毫秒)
        if (!SetCommTimeouts(m_hSerial, &timeouts)) {
            qDebug() << "Failed to set serial port timeouts.";
            CloseHandle(m_hSerial);
            return false;
        }

        DCB dcbSerialParams = {0};
        dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
        if (!GetCommState(m_hSerial, &dcbSerialParams)) {
            qDebug() << "Error getting serial port state!";
            CloseSerialPort();
            return false;
        }

        dcbSerialParams.BaudRate = static_cast<DWORD>(baudRate);
        dcbSerialParams.ByteSize = 8;
        dcbSerialParams.StopBits = ONESTOPBIT;
        dcbSerialParams.Parity = EVENPARITY;
        if (!SetCommState(m_hSerial, &dcbSerialParams)) {
            qDebug() << "Error setting serial port state!";
            CloseSerialPort();
            return false;
        }

        qDebug() << "Serial port opened successfully!";
        return true;
    }

    void CloseSerialPort() {
        if (m_hSerial != INVALID_HANDLE_VALUE) {
            CloseHandle(m_hSerial);
            m_hSerial = INVALID_HANDLE_VALUE;
            qDebug() << "Serial port closed.";
        }
    }

    qint64 WriteData(const QByteArray& data) {
        if (m_hSerial != INVALID_HANDLE_VALUE) {
            DWORD bytesWritten;
            if (WriteFile(m_hSerial, data.constData(), data.size(), &bytesWritten, nullptr)) {
                return static_cast<qint64>(bytesWritten);
            }
        }
        return -1;
    }

    QByteArray ReadData() {
        QByteArray data;
        if (m_hSerial != INVALID_HANDLE_VALUE) {
            char buffer[150];
            DWORD bytesRead;
            if (ReadFile(m_hSerial, buffer, static_cast<DWORD>(150), &bytesRead, nullptr) && bytesRead > 0) {
                data.append(buffer, static_cast<int>(bytesRead));
            }
        }
        return data;
    }

   private:
    HANDLE m_hSerial;
};

int main() {
    CSerialPort m_serialPortObj;
    // 查找可用串口
    QStringList list = m_serialPortObj.CheckSerialPort();
    qDebug() << list;

    // 打开串口
    bool m_bSerialPortOpen = true;
    m_serialPortObj.OpenSerialPort("COM1", 9600);
    // 读取串口数据
    QtConcurrent::run([&]() {
        while (m_bSerialPortOpen) {
            QByteArray readData = m_serialPortObj.ReadData();
            qDebug() << readData;
            Sleep(500);
        }
    });
    // 向串口写数据
    QByteArray data;
    data.append(0xFF);
    data.append(0x01);
    data.append("\x00", 1);
    data.append(0x4B);
    data.append(0x23);
    data.append(0x28);
    data.append(0x97);
    m_serialPortObj.WriteData(data);
    
    // 关闭串口
    m_bSerialPortOpen = false;
    m_serialPortObj.CloseSerialPort();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值