布丁君别闹 2021-09-22 15:44 采纳率: 0%
浏览 192
已结题

QtSerialPort 串口 多线程框架 长时间运行后会出现收不到数据的情况

数据量 每毫秒6个字节

主要采用单生产者单消费者模型:
1.生产者moveToThread,线程扫描串口数据,入消息队列,释放信号量,同时emit信号;
2.消费者接收到消息,获取信号量,从消息队列中获取数据。

生产者:


#include "serialcom.h"

SerialCom::SerialCom()
{
    m_port = “COM1”;
    m_rate = "115200";

    m_sem = new QSemaphore(0);
    m_updatesem = new QSemaphore(0);

  m_thread_running = false;
  m_thread = new QThread();
    
    m_serial = new QSerialPort(m_thread);
    moveToThread(m_thread);

    // 绑定线程循环体
    connect(m_thread, SIGNAL(started()), this, SLOT(Serial_ReadyRead()));

}

bool SerialCom::IsConnected()
{
    if (m_serial)
    {
        //if (m_serial->isOpen())
        if (m_thread_running)
        {
            return true;
        }
    }
    return false;
}

QString SerialCom::GetPort()
{
    return m_port;
}

void SerialCom::ScanPort()
{
    if(m_serial != nullptr)
    {
        foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
        {
            QSerialPort serial;
            serial.setPort(info);

            if(serial.open(QIODevice::ReadWrite))
            {
                //qDebug() << "port:" << serial.portName();
                m_port = serial.portName();
                serial.close();
                return; // use the first avilable one
            }
        }
    }
}

QString SerialCom::GetStatus()
{
    return m_status;
}

bool SerialCom::Connect(char *pPort, char *pRate)
{
    if (m_serial == nullptr)
    {
        return false;
    }

    if (!IsConnected())
    {
        QString port = m_port;
        qint32 rate = m_rate.toInt();

        // port
        if (pPort != nullptr)
        {
            port = QString(pPort);
            m_port = port;
        }

        // rate
        if (pRate != nullptr)
        {
            rate = QString(pRate).toInt();
            m_rate = QString(pRate);

        }

        m_serial->setPortName(port);
        m_serial->setBaudRate(rate);
        m_serial->setDataBits(QSerialPort::Data8);
        m_serial->setParity(QSerialPort::NoParity);
        m_serial->setStopBits(QSerialPort::OneStop);
        m_serial->setFlowControl(QSerialPort::NoFlowControl);

        m_serial->setReadBufferSize(150);

        if (m_serial->open(QIODevice::ReadWrite))
        {
            m_thread_running = true;
            m_thread->start();
            qDebug() << "port:" << m_port << "rate:" << m_rate;
            m_status = ("port:" + port + ",rate:" + QString::number(rate));
            return true;
        }
        else
        {
            qDebug() << "Open COM ERROR!!!" << "port:" << port << "rate:" << rate;
            m_status = ("port:" + port + ",rate:" + QString::number(rate));
            return false;
        }

    }

    return true;
}

bool SerialCom::Disconnect()
{
    if (m_thread != nullptr)
    {
        m_thread_running = false;
        m_thread->quit();
        m_thread->wait();
    }

    if (m_serial != nullptr)
    {
        m_serial->close();
    }

    return true;
}


int SerialCom::GetPacket(QByteArray &message, int timeout)
{
    if (timeout == -1) {
        timeout = this->timeout;
    }

    if (m_sem->tryAcquire(1, timeout))
    {
        message = m_message.first();
        m_message.pop_front();

        return 0;
    }
    else
    {
        //qDebug() << "SerialCom::GetPacket() recv timeout!" << m_message.size();
        return -1;
    }
}

void SerialCom::PutPacket(QByteArray &message)
{
    
        m_serial->write(message.data(), message.size());

        msecSleep(15);
}

void SerialCom::Serial_ReadyRead()
{

    while (true) {
        if (m_serial != nullptr && m_thread_running)
        {
            if (m_serial->bytesAvailable())
            {
                QByteArray rdata;

                rmessage.resize(m_serial->bytesAvailable());

                {
                    //qDebug() << "bytesAvailable:" << m_serial->bytesAvailable();

                    rdata = m_serial->readLine();

                }

                {
//                        qDebug() << "recv:" << rdata.toHex() << rdata.size() << m_sem->available();

                    m_message.push_back(rdata);
                    m_sem->release();

                    emit recvMsg();
                }

            }
        }
        else
        {
            return;
        }
        QThread::msleep(1);
    }
}

消费者:

#include "home.h"
#include "ui_home.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    start();
}

Widget::~Widget()
{
    stop();

    delete ui;
}

void Widget::start()
{
    m_scom = new SerialCom();

        m_scom->ScanPort();
        m_scom->Connect();

    if(m_scom->IsConnected())
    {
        connect(m_scom,SIGNAL(recvMsg()),this,SLOT(msgSwitch()));//msgSwitch()为自定义槽

        //QMessageBox::information(NULL, "成功", "连接成功!\n"+m_icom->GetStatus());
    }
    else
    {
        QMessageBox::critical(NULL, "失败", "连接失败,端口被占用!\n"+m_icom->GetStatus());
        QTimer::singleShot(200, this, SLOT(jumpQuit()));
    }
}


int Widget::stop() const
{
    if (m_scom != nullptr)
        {
            m_scom->Disconnect();
            delete m_scom;
        }
    }

    return 0;
}


void Widget::msgSwitch()
{
    QByteArray msg;

    if (!(m_icom->GetPacket(msg, 1)))
    {
        // 获取到包
        qDebug() << msg.toHex() << "Recv data lenth:" << msg.size();
    }

}
  • 写回答

1条回答 默认 最新

  • 有问必答小助手 2021-09-24 09:50
    关注

    你好,我是有问必答小助手,非常抱歉,本次您提出的有问必答问题,技术专家团超时未为您做出解答


    本次提问扣除的有问必答次数,将会以问答VIP体验卡(1次有问必答机会、商城购买实体图书享受95折优惠)的形式为您补发到账户。


    因为有问必答VIP体验卡有效期仅有1天,您在需要使用的时候【私信】联系我,我会为您补发。

    评论

报告相同问题?

问题事件

  • 系统已结题 9月30日
  • 修改了问题 9月22日
  • 修改了问题 9月22日
  • 修改了问题 9月22日
  • 展开全部

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值