Linux环境下Qt多线程串口功能的实现浅析


前言

在实际工程项目中,一般是在Linux环境下,使用Qt开发多线程串口通信功能的上位机软件,不多逼逼,直接上正文:

一、自定义串口类

代码如下(示例):

CCtrlSerial::CCtrlSerial(const QString & portName, const int & baudRate, const QString & parity,
                         const QString & dataBits, const QString & stopBits, const QString & flowControl,
                         QObject * parent)
    : QObject(parent)
{
    // 对串口配置参数进行解析
    int opt_baudrate = baudRate;

    QSerialPort::Parity opt_parity = QSerialPort::Parity::NoParity;
    if (parity == "NoParity")
    {
        opt_parity = QSerialPort::Parity::NoParity;
    }
    else if (parity == "OddParity")
    {
        opt_parity = QSerialPort::Parity::OddParity;
    }
    else if (parity == "EvenParity")
    {
        opt_parity = QSerialPort::Parity::EvenParity;
    }

    QSerialPort::DataBits opt_dataBits = QSerialPort::DataBits::Data8;
    if (dataBits == "Data5")
    {
        opt_dataBits = QSerialPort::DataBits::Data5;
    }
    else if (dataBits == "Data6")
    {
        opt_dataBits = QSerialPort::DataBits::Data6;
    }
    else if (dataBits == "Data7")
    {
        opt_dataBits = QSerialPort::DataBits::Data7;
    }
    else if (dataBits == "Data8")
    {
        opt_dataBits = QSerialPort::DataBits::Data8;
    }

    QSerialPort::StopBits opt_stopBits = QSerialPort::StopBits::OneStop;
    if (stopBits == "OneStop")
    {
        opt_stopBits = QSerialPort::StopBits::OneStop;
    }
    else if (stopBits == "OneAndHalfStop")
    {
        opt_stopBits = QSerialPort::StopBits::OneAndHalfStop;
    }
    else if (stopBits == "TwoStop")
    {
        opt_stopBits = QSerialPort::StopBits::TwoStop;
    }

    QSerialPort::FlowControl opt_flowControl = QSerialPort::FlowControl::NoFlowControl;
    if (flowControl == "NoFlowControl")
    {
        opt_flowControl = QSerialPort::FlowControl::NoFlowControl;
    }
    else if (flowControl == "SoftwareControl")
    {
        opt_flowControl = QSerialPort::FlowControl::SoftwareControl;
    }
    else if (flowControl == "HardwareControl")
    {
        opt_flowControl = QSerialPort::FlowControl::HardwareControl;
    }

    threadSerial = new QThread(nullptr);
    workerSerial = new CSerialport(portName, opt_baudrate, opt_parity, opt_dataBits, opt_stopBits, opt_flowControl, nullptr);
    workerSerial->moveToThread(threadSerial);
    connect(threadSerial, &QThread::started, workerSerial, &CSerialport::onInitSerial);

    connect(threadSerial, &QThread::finished, workerSerial, &CSerialport::deleteLater);
    connect(threadSerial, &QThread::finished, threadSerial, &QThread::deleteLater);

}

二、启动串口工作

代码如下(示例):

void CDeviceSerial::openDevice()
{
    // 设备如果已经打开则关闭
    if (flagOpen)
    {
        closeDevice();
    }

    // 创建工作类对象 - 串口 0
    pSerial0 = new CCtrlSerial("/dev/ttyS0", 115200, "NoParity", "Data8", "OneStop", "NoFlowControl", this);    // 指定了 parent,便于自动释放
    connect(pSerial0, &CCtrlSerial::sigErrorOccurred, this, &CDeviceSerial::onErrorOccurred);

    // 创建工作类对象 - 串口 2
    pSerial2 = new CCtrlSerial("/dev/ttyS2", 115200, "NoParity", "Data8", "OneStop", "NoFlowControl", this);    // 指定了 parent,便于自动释放
    connect(pSerial2, &CCtrlSerial::sigErrorOccurred, this, &CDeviceSerial::onErrorOccurred);
    connect(pSerial2, &CCtrlSerial::sigReadFromSerial, this, &CDeviceSerial::onReadFromSerial2);

    // 创建工作类对象 - 串口 3
    pSerial3 = new CCtrlSerial("/dev/ttyS3", 115200, "NoParity", "Data8", "OneStop", "NoFlowControl", this);    // 指定了 parent,便于自动释放
    connect(pSerial3, &CCtrlSerial::sigErrorOccurred, this, &CDeviceSerial::onErrorOccurred);

    // 创建工作类对象 - 串口 4
    pSerial4 = new CCtrlSerial("/dev/ttyS4", 115200, "NoParity", "Data8", "OneStop", "NoFlowControl", this);    // 指定了 parent,便于自动释放
    connect(pSerial4, &CCtrlSerial::sigErrorOccurred, this, &CDeviceSerial::onErrorOccurred);

    // 创建工作类对象 - 串口 5
    pSerial5 = new CCtrlSerial("/dev/ttyS5", 115200, "NoParity", "Data8", "OneStop", "NoFlowControl", this);    // 指定了 parent,便于自动释放
    connect(pSerial5, &CCtrlSerial::sigErrorOccurred, this, &CDeviceSerial::onErrorOccurred);
    connect(pSerial5, &CCtrlSerial::sigReadFromSerial, this, &CDeviceSerial::onReadFromSerial5);

    // 创建工作类对象 - 串口 6
    pSerial6 = new CCtrlSerial("/dev/ttyS6", 115200, "NoParity", "Data8", "OneStop", "NoFlowControl", this);    // 指定了 parent,便于自动释放
    connect(pSerial6, &CCtrlSerial::sigErrorOccurred, this, &CDeviceSerial::onErrorOccurred);
    connect(pSerial6, &CCtrlSerial::sigReadFromSerial, this, &CDeviceSerial::onReadFromSerial6);

    // 必要的初始化变量
    rdbuf2.clear();
    rdbuf5.clear();
    rdbuf6.clear();
    rdbuf7.clear();

    // 启用串口工作
    //pSerial0->initParams();
    pSerial2->initParams();
    pSerial3->initParams();
    pSerial4->initParams();
    pSerial5->initParams();
    pSerial6->initParams();

    flagOpen = true;    // 置标识
    return;
}

开线程(关键点!!!)

void CCtrlSerial::initParams()
{
    // 信号 - 槽
    connect(workerSerial, &CSerialport::sigReadFromSerial, this, &CCtrlSerial::sigReadFromSerial);
    connect(workerSerial, &CSerialport::sigErrorOccurred, this, &CCtrlSerial::sigErrorOccurred);
    connect(workerSerial, &CSerialport::sigBytesWrited, this, &CCtrlSerial::sigBytesWrited);
    connect(this, &CCtrlSerial::sigWriteToSerial, workerSerial, &CSerialport::onWriteToSerial);

    threadSerial->start();    // 开启线程
}

1.串口写入数据

代码如下(示例):

void CSerialport::onWriteToSerial(const QByteArray & ba)
{
    if (ba.isEmpty())
    {
        return;
    }

    if ((pSport == nullptr) || (!flagOpen))
    {
        return;
    }

    bufWrite.clear();
    bufWrite.append(ba);

    qint64 nums = pSport->write(bufWrite);
    if (nums != -1)
    {
        int len = static_cast<int>(nums);
        bufWrite.remove(0, len);

        if (len > 0)
        {
            sigBytesWrited(len);
        }
    }

    return;
}

2.串口读取数据

代码如下(示例):

void CSerialport::onProcessReadData()
{
    if ((pSport == nullptr) || (!flagOpen))
    {
        return;
    }

    qint64 nums = pSport->bytesAvailable();
    if (nums > 0)
    {
        bufRead.clear();
        bufRead.append(pSport->readAll());

        if (bufRead.size() > 0)    // 这里用 size(),因为 count() 和 length() 其实也是 size()
        {
            emit sigReadFromSerial(bufRead);    // 发射信号
        }
    }

    return;
}

总结

以上为个人以前工作中,实际落地项目的代码节选内容,分享的目的是为了更好的帮助有真正需要帮助的人,如有疑问,欢迎拍砖。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值