ARM Linux Qt 串口编程详解

在嵌入式系统中,ARM Linux 与 Qt 结合使用串口(Serial Port)进行通信是一个常见的应用场景,本文将详细介绍如何在 ARM Linux 环境下,使用 Qt 框架进行串口通信,包括环境配置、Qt 串口类的使用、数据读写操作以及常见问题的解决方法。
1. 环境准备
1 硬件要求
ARM 开发板:如树莓派、BeagleBone 等支持 Linux 的 ARM 设备。
串口设备:如 USB 转串口模块、RS232 接口等。
2 软件要求
操作系统:ARM Linux 发行版,如 Ubuntu ARM、Debian ARM 等。
Qt 框架:推荐使用 Qt 5 或 Qt 6。
开发工具:GCC、G++、make、qmake 等。
2. Qt 串口类介绍
Qt 提供了QSerialPort 类用于串口通信,该类属于 Qt Serial Bus 模块,支持串口的打开、配置、读写操作等。
1 主要功能
打开和关闭串口
设置波特率、数据位、停止位、校验位等参数
读取和写入数据
监听串口状态变化
2 常用方法
| 方法 | 描述 |
QSerialPort::setPortName(const QString &name) |
设置串口名称,如/dev/ttyS0 |
QSerialPort::setBaudRate(qint32 baudRate) |
设置波特率,如9600 |
QSerialPort::setDataBits(QSerialPort::DataBits dataBits) |
设置数据位,如QSerialPort::Data8 |
QSerialPort::setParity(QSerialPort::Parity parity) |
设置校验位,如QSerialPort::NoParity |
QSerialPort::setStopBits(QSerialPort::StopBits stopBits) |
设置停止位,如QSerialPort::OneStop |
QSerialPort::open(QIODevice::OpenMode mode) |
打开串口,模式可以是ReadOnly、WriteOnly 或ReadWrite |
QSerialPort::close() |
关闭串口 |
QSerialPort::write(const char *data, qint64 len) |
向串口写入数据 |
QSerialPort::read(char *data, qint64 maxSize) |
从串口读取数据 |
QSerialPort::bytesAvailable() |
获取可读取的数据字节数 |
QSerialPort::error() |
获取串口错误状态 |
3. 串口配置步骤
3.1 引入 Qt Serial Bus 模块
在项目的.pro 文件中添加:
QT += serialport
3.2 创建并配置QSerialPort 对象
#include <QSerialPort>
#include <QSerialPortInfo>
// 创建串口对象
QSerialPort serial;
// 设置串口名称
serial.setPortName("/dev/ttyS0"); // 根据实际串口名称修改
// 设置波特率
serial.setBaudRate(QSerialPort::Baud9600);
// 设置数据位
serial.setDataBits(QSerialPort::Data8);
// 设置校验位
serial.setParity(QSerialPort::NoParity);
// 设置停止位
serial.setStopBits(QSerialPort::OneStop);
// 设置流控
serial.setFlowControl(QSerialPort::NoFlowControl);
3 打开串口
if (serial.open(QIODevice::ReadWrite)) {
qDebug() << "串口打开成功!";
} else {
qDebug() << "串口打开失败:" << serial.errorString();
}
4 数据读写操作
3.4.1 写入数据

QByteArray data = "Hello Serial"; serial.write(data); serial.flush(); // 确保数据发送完毕
3.4.2 读取数据
// 连接信号槽,监听数据可读
connect(&serial, &QSerialPort::readyRead, this, &YourClass::handleReadyRead);
void YourClass::handleReadyRead() {
QByteArray data = serial.readAll(); // 读取所有可读数据
qDebug() << "接收到数据:" << data;
}
5 关闭串口
serial.close();
4. 示例代码
以下是一个简单的 Qt 应用示例,演示如何打开串口、发送和接收数据。
#include <QCoreApplication>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QObject>
class SerialHandler : public QObject {
Q_OBJECT
public:
SerialHandler(QObject *parent = nullptr) : QObject(parent) {
setupSerial();
}
private slots:
void handleReadyRead() {
QByteArray data = serial.readAll();
qDebug() << "接收到数据:" << data;
}
void handleError(QSerialPort::SerialPortError error) {
if (error != QSerialPort::NoError) {
qDebug() << "串口错误:" << serial.errorString();
}
}
private:
QSerialPort serial;
void setupSerial() {
// 配置串口参数
serial.setPortName("/dev/ttyS0"); // 根据实际修改
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
// 连接信号槽
connect(&serial, &QSerialPort::readyRead, this, &SerialHandler::handleReadyRead);
connect(&serial, &QSerialPort::errorOccurred, this, &SerialHandler::handleError);
// 打开串口
if (serial.open(QIODevice::ReadWrite)) {
qDebug() << "串口打开成功!";
// 发送数据示例
QByteArray data = "Hello from Qt!";
serial.write(data);
serial.flush();
} else {
qDebug() << "串口打开失败:" << serial.errorString();
}
}
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
SerialHandler handler;
return a.exec();
}
5. 常见问题与解决方法
1 无法打开串口
原因:
串口名称错误。
权限不足,当前用户没有访问串口设备的权限。
串口被其他进程占用。
解决方法:
确认串口名称正确,可以使用ls /dev/tty 查看可用串口。
使用sudo 提权运行程序,或将当前用户添加到dialout 组(通常拥有串口权限)。
确保没有其他程序占用串口资源。
2 数据发送或接收失败
原因:
串口参数配置不匹配(波特率、数据位等)。
硬件连接问题。
串口缓冲区未及时处理,导致阻塞。
解决方法:
确认发送端和接收端的串口参数一致。

检查物理连接,确保串口线连接稳固。
在接收数据时,及时处理readyRead 信号,避免缓冲区溢出。
6. 相关问题与解答
问题 1:如何在 Qt 中动态列出所有可用的串口?
解答:
可以使用QSerialPortInfo 类来获取系统中所有可用的串口信息,以下是一个示例代码:
#include <QSerialPortInfo>
#include <QDebug>
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
qDebug() << "端口名称:" << info.portName();
qDebug() << "描述:" << info.description();
qDebug() << "制造商:" << info.manufacturer();
qDebug() << "系统位置:" << info.systemLocation();
qDebug() << "----------------------------------------";
}
此代码会遍历并打印出系统中所有可用的串口及其详细信息,方便动态选择串口。
问题 2:如何处理串口通信中的异步事件?
解答:
串口通信通常是异步的,为了避免阻塞主线程,建议将串口操作放在独立的线程中进行处理,可以通过信号与槽机制来处理各种异步事件,如数据到达、错误发生等,以下是一个简单的处理方式:
1、创建工作线程:将QSerialPort 对象放在一个独立的线程中,避免影响主界面响应。
2、使用信号与槽:通过连接readyRead、errorOccurred 等信号到相应的槽函数,处理数据读写和错误。
3、线程安全:确保在多线程环境下对共享资源的访问是线程安全的,可以使用互斥锁(QMutex)或其他同步机制。
示例代码:
#include <QThread>
#include <QSerialPort>
#include <QDebug>
class SerialWorker : public QObject {
Q_OBJECT
public:
SerialWorker(QString portName) : m_portName(portName) {}
public slots:
void process() {
m_serial.setPortName(m_portName);
m_serial.setBaudRate(QSerialPort::Baud9600);
m_serial.setDataBits(QSerialPort::Data8);
m_serial.setParity(QSerialPort::NoParity);
m_serial.setStopBits(QSerialPort::OneStop);
m_serial.setFlowControl(QSerialPort::NoFlowControl);
connect(&m_serial, &QSerialPort::readyRead, this, &SerialWorker::handleReadyRead);
connect(&m_serial, &QSerialPort::errorOccurred, this, &SerialWorker::handleError);
if (!m_serial.open(QIODevice::ReadWrite)) {
emit errorOccurred(m_serial.errorString());
} else {
qDebug() << "串口打开成功!";
}
}
signals:
void errorOccurred(const QString &error);
void dataReceived(const QByteArray &data);
private slots:
void handleReadyRead() {
QByteArray data = m_serial.readAll();
qDebug() << "接收到数据:" << data;
emit dataReceived(data);
}
void handleError(QSerialPort::SerialPortError error) {
if (error != QSerialPort::NoError) {
emit errorOccurred(m_serial.errorString());
}
}
private:
QSerialPort m_serial;
QString m_portName;
};
然后在主线程中启动工作线程:
#include <QThread>
#include "SerialWorker.h"
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QThread workerThread;
SerialWorker worker("/dev/ttyS0"); // 根据实际修改
worker.moveToThread(&workerThread);
QObject::connect(&workerThread, &QThread::started, &worker, &SerialWorker::process);
QObject::connect(&worker, &SerialWorker::dataReceived, [](const QByteArray &data){
// 处理接收到的数据
});
QObject::connect(&worker, &SerialWorker::errorOccurred, [](const QString &error){
qDebug() << "串口错误:" << error;
});
workerThread.start();
return a.exec();
}
通过这种方式,可以将串口操作与主线程分离,确保应用程序的响应性和稳定性。
到此,以上就是小编对于“armlinuxqt串口”的问题就介绍到这了,希望介绍的几点解答对大家有用,有任何问题和不懂的,欢迎各位朋友在评论区讨论,给我留言。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!