一、通过 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;
}