QT中Serialport同步异步接收数据 -- 完善

串口用了无数次,没想到到QT这蹩脚了。基本的配置直接看QT的示例代码就行了,接收的时候分同步接收和异步接收。

异步接收:

//.h中声明
QByteArray rxData;

//cpp构造函数中绑定接收事件
connect(serial0, &QSerialPort::readyRead, this, &SerialBoard::readData);

//直接读取全部数据
void SerialBoard::readData()
{
    rxData = serial0->readAll();
} 

异步有个问题,当数据较多时,readAll不能一次全读完,因为接收数据也需要时间,但是readyRead不能设置触发阈值,接收到数据就触发readData事件了。

QT示例中又block传输方法,在单独线程中

 
while (serial.waitForReadyRead(10))
     responseData += serial.readAll();

嗯,不错,但感觉这只适合传输文件之类的,当进入readData槽后再wait时有新的数据进来就不会再次触发槽函数,而是wait返回true接收数据,没数据后只能等wait 10ms超时后返回false才返回,显然有点拖慢系统的速度。我的协议中只是有些命令数据稍大,看了看别人的例子,可以用阻塞和非阻塞接收数据。阻塞就是加延时,然后再读数。我采用加定时器同步接收

 

 
    //.h中加一个
QTimer *rxTimer;
//cpp构造函数中增加定时器初始化,单次定时,超时触发槽函数,槽函数自己注册
    connect(serial0, &QSerialPort::readyRead, this, &SerialBoard::readData);
    rxTimer = new QTimer(this);
    QObject::connect( rxTimer, &QTimer::timeout,this,&SerialBoard::CheckData);
    rxTimer->setSingleShot(true);
    rxTimer->setInterval(0);

 

 

 

void SerialBoard::readData()
{
    //数据追加
    rxData += serial0->readAll();
    //rxTimer->setInterval(0);
    //开启10ms定时器,10ms内没再次接收到数据就超时了
    rxTimer->start(10);
 
}
void SerialBoard::CheckData()
{
    //超时,表示此次传输完成,开始处理数据包,这里是校验接收的数据是否正确,然后将结果用回调方式传出去
    rxTimer->stop();
    errordata=0;
    if(rxData.size() != TESTSIZE)
    {
       errordata = TESTSIZE - rxData.size();
    }
    qDebug() << "serial0 Data size " + QString::number(rxData.length(),10);
    for(int i=0;i
    {
        if(rxData[i] != (char)(i&0xFF))
        {
            errordata++;
        }
    }
    m_psink->OnReaddataFinished("serial0 rx/total:"+QString::number(errordata,10)+"/" + QString::number(TESTSIZE,10)+"\n");
}

暂时先这么用着,感觉还有点不完美,以后再追加。

=继续补充==================================================================================

在使用中发现 串口缓冲区并没有起到作用

serial0->setReadBufferSize(2000);

设置的2000个字节缓冲,事实没有read完数据,后面的数据会丢掉很多,可能底层驱动没做内存缓冲,硬件FIFO肯定比较小了。

于是槽函数做缓冲,数据处理定时处理。

connect(serial0, &QSerialPort::readyRead, this, &SerialTelephone::readData);

    //100ms定时器---------------------------------------------------
    m_pTimer = new QTimer(this);
    connect(m_pTimer, SIGNAL(timeout()), this, SLOT(Timer1Handle()));
    m_pTimer->start(100);

void SerialTelephone::readData()
{
    rxData += serial0->readAll();
//    QString text = "telephone board rx: ";
//    QByteArray str = rxData.toHex().toUpper();
//    for(int i = 0; i < str.size(); i+=2)
//        text = text + " 0x" + str.at(i) + str.at(i+1);
//    qDebug() << text;

    timeoutCount++;
}

void SerialTelephone::Timer1Handle()
{
    if(timeoutCount > 0)
    {
        while(0 == decode(rxData));

    }
}

decode处理数据时,需要拆包处理,因为100ms可能收到多个数据包,有不完整的数据包时需要剔除数据,配合协议来完善,例如经典的使用0x7E包头,内容0x7D 0x5E替换0x7E,0x7D 0x5D 替换0x7D。

 

 

 

 

 

你可能感兴趣的:(液晶屏QT,Serialport,同步接收)