前面解析和优化了串口接收相关的代码,现在我们巩固一下,假设外部设备一直发送数据,频率为50Hz,每帧数据包含帧头“0x55 0xAA 0x55 0xAA”,数据,和校验。波特率是921600bps,要求数据接收不丢帧,且实时输出每帧数据。
1、数据接收与解析:创建一个单独的线程或者使用Qt的事件循环机制处理串口接收到的数据。在数据接收的回调函数中,解析每一帧数据,确保处理速度足够快以便实时处理数据。
2、实时输出每 帧数据:当解析到完整的一帧数据时,发送信号通知主线程或者相应的界面组件进行处理和显示,可以使用Qt的信号与槽机制来实现这一点。
3、多线程处理:由于数据接收和解析需要与界面交互,可以考虑使用多线程来避免阻塞界面。将串口通信和数据处理放在一个独立的线程中进行,使用信号与槽来与界面进行通信。
4、异常处理:考虑到串口通信可能出现异常(如通信中断、数据错误等),需要添加适当的异常处理机制,以确保系统的稳定性和可靠性。
下面是一个基本的示例:
#include <QCoreApplication>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
class SerialPortReader : public QObject
{
Q_OBJECT
public:
SerialPortReader(QSertialPort *serialPort,QObject *parent = nullptr)
:QObject(parent),m_serialPort(serialPort)
{
connect(m_serialPort,&QSerialPort::readyRead,this,&SerialPortReader::handleReadyRead);
}
signals:
void frameReceived(const QByteArray &frame);
private slots:
void handleReadyRead()
{
m_buffer.append(m_serialPort->readAll());
while(m_buffer.size()>=FRAME_SIZE)
{
int headerIndex = m_buffer.indexof(HEADER);
if(headerIndex != -1)
{
QByteArray frame = m_buffer.mid(headerIndex,FRAME_SIZE);
emit frameReceived(frame);
}else
{
m_buffer.clear();
}
}
}
private:
QSerialPort *m_serialPort;
QByteArray m_buffer;
static const int FRAME_SIZE = 10;
static const QByteArray HEADER;
}
const QByteArray SerialPortReader::HEADER = QByteArray::fromHex("55AA55AA");
int main(int argc,char *argv[])
{
QCoreApplication a (argc,argv);
QSerialPort serialPort;
serialPort.setPortName("COM1");
serialPort.setBaudRate(QSerialPort::Baud921600);
serialPort.setDataBits(QSerialPort::Data8);
serialPort.setParity(QSerialPort::NoParity);
serialPort.setStopBits(QSerialPort::OneStop);
serialPort.setFlowControl(QSerialPort::NoFlowControl);
if(!serialPort.open(QIODevice::ReadOnly))
{
qDebug()<<"Falied to open serial port :"<<serialPort.errorString();
return -1;
}
SerialPortReader serialPortReader(&serialPort);
QObject::connect(&serialPortReader,&SerialPortReader::frameReceived,[](const QByteArray &frame )
{
qDebug()<<"Received frame:"<<frame.toHex();
}
);
return a.exec();
}