QT之串口通信和多线程处理

Posted on 2021-07-07 22:05  绿叶落秋风  阅读(4874)  评论(0编辑  收藏  举报

前言

  使用QT的多线程编程,完成串口通信助手的设计。

实施

Qt5下的串口编程

  使用QT5.12中自带的QSerialPort和QSerialPortInf的类实现对串口硬件的访问,通过对类的方法进行操作,完成整个串口的控制。整个操作基于类的实例,能够快速部署。这里需要明确层次的概念。串口类,提供了整个串口通信需要的方法,可以直接用于串口的使用。打开串口,即指示该类打开底层串口缓存区,建立连接,实现数据的访问。读取数据,在打开串口的条件下,对缓存区的数据进行操作,确保可以得到正确的数据。这三个层次就是串口编程的基本概念。为了降低数据处理对整个界面的影响,将数据通过变量传递给多线程下的数据处理模块。

串口部分的功能设计

//采用指针分配空间的方法实现类的操作
void
DialogUart::on_btnUartOpen_clicked() { serial = new QSerialPort; qDebug()<<"uart is open"; }

void DialogUart::on_btnUartClose_clicked() { delete serial; qDebug()<<"uart is close"; } //采用函数的方法实现串口配置及打开 void DialogUart::on_btnConnect_clicked() { //设置串口名 serial->setPortName("COM1"); //设置波特率 serial->setBaudRate(QSerialPort::Baud9600); //设置数据位数 serial->setDataBits(QSerialPort::Data8); //设置奇偶校验 serial->setParity(QSerialPort::NoParity); //设置停止位 serial->setStopBits(QSerialPort::OneStop); //设置流控制 serial->setFlowControl(QSerialPort::NoFlowControl); serial->open(QIODevice::ReadWrite); } void DialogUart::on_btnDisConnect_clicked() { serial->close(); } //采用按键控制接收数据(仅用于测试,实际使用中应使用信号触发,防止读取多余的数据) void DialogUart::on_readAll_clicked() { QByteArray buf_read; buf_read = serial->readAll(); QString recv = ui->readText->toPlainText(); recv += QString(buf_read); ui->readText->clear(); ui->readText->append(recv); } //采用按键控制写入 void DialogUart::on_writeAll_clicked() { QByteArray buf_write; buf_write = ui->writeText->text().toUtf8(); serial->write(buf_write); }

  整个控制还是比较清晰的。这里基本上满足了串口调试的常用需求,但是缺少一些控制界面。这些通过控件关联到参数即可。

  在这个简单的串口控制的基础上,增加一些多线程控制的功能,用于实现一些数据的自动化处理。

多线程部分的编程

  这里多线程采用简单的继承QThread的方法,利用run函数的重构进行部分复杂功能的后台运行。根据需求,这里采用正则匹配的方法对串口自动接收的数据进行分割,确保串行数据可以转化为预期的并行数据。数据通过文件在不同的界面之间进行传输,暂时不协调,使用按钮模拟流程。

    QFile fil(QDir::currentPath()+".txt");
    fil.open(QIODevice::ReadOnly);
    char buf[3];
    qint64  addr;
    qint64  length;
    QString buf_exp;
    QRegExp exp("[0-9a-fA-F]");
    addr=0;
    while(!m_toStop)
    {
        fil.seek(addr);
        length = fil.read(buf,sizeof (buf));
        buf_exp = QString::fromLocal8Bit(buf);
        if(! exp.indexIn(buf_exp))
        {
            qDebug()<<buf_exp;
            addr=addr+length;
        }
        else
        {
            qDebug()<<"error";
            addr=addr+1;
        }
        if(addr>=fil.size())
        {
            fil.close();
            m_toStop = true;
        }
    }

重构的run函数可以用于持续读取和匹配字符函数。本段代码展示了单位宽度正则匹配字符的简易操作方法,主要用于记录和演示。

 结果

初步验证了使用串口类完成数据通信和使用多线程完成通信后的数据匹配处理的操作,为下一步的QT增加处理模型提供了解决方法。

附件

基于Qt5.12的工程