气象自动监测站QT程序设计(二):串口通信与数据处理

    由于目前制作的下位机是使用串口通信,因此需要使用QT中的串口解决方法来获取通信中的数据。在本文中您将看到QT对串口的使用非常简单易用,如果采用的是网络通信,QT也提供了同样简便的解决方法。

     串口操作使用的是QT5支持的QtSerialPort类和QSerialPortInfo类,需要在程序中挂载相应的头文件:

#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>

     另外还需要在工程文件.pro中添加一个QT值:

QT    +=  serialport

     这样您就已经可以在程序中使用串口了,根据需求来决定QSerialPort对象是在类中定义还是在函数中定义。对QSerialPort对象的属性设置也很常规,您需要决定的只是应该在窗体的构造函数中连接串口,还是应该在某个控件的槽函数中连接串口。
     串口属性配置如下:

mySerialport = new QSerialPort();
    mySerialport->setPortName("COM3");  //端口名称
    if(mySerialport->open(QIODevice::ReadWrite))
    {
        mySerialport->setBaudRate(9600); //波特率
        mySerialport->setDataBits(QSerialPort::Data8); //数据位
        mySerialport->setParity(QSerialPort::NoParity); //校验
        mySerialport->setStopBits(QSerialPort::OneStop); //停止位
        mySerialport->setFlowControl(QSerialPort::NoFlowControl); //流控制
        connect(mySerialport, SIGNAL(readyRead()), this, SLOT(update()));
    }
    else
        QMessageBox::warning(NULL, "warning", "Serial Port is occupied", QMessageBox::Retry);

     其它的参数各位都很熟悉,比较关键的一点是QT中的串口有一个机制,每当接收到一个数据时都会抛出一个signal(readyRead())表示已经可以读取串口数据。通常的做法都是将这个信号和某个槽函数连接起来,每当接收到串口数据就可以在槽函数中进行相应的实时处理。此处我绑定了update函数,这个函数是我自定义的。

void AutomaticStation::update()
{
    recData = mySerialport->readAll();       //读取数据
    QString buf;
    int showdata;

    buf = ShowHex(recData);
    showdata = buf.toInt();
    ......                            //数据处理
}

     槽函数中通常的做法是用QSerialPort类的readAll函数将串口缓冲区中的所有数据都读出来,该类还提供了一些其它的read函数,如读取指定长度等等。这里读出的recData是一个QByteArray类型的变量,可以存储一个字节。如果希望像普通的数据一样处理,可以用一个自定义函数ShowHex将QByteArray类型转换为字符串类型,还可以再用QString类的toInt和toFloat等方法将它转化为常规数字类型。自定义的ShowHex函数如下所示:

QString AutomaticStation::ShowHex(QByteArray str)
{
    QDataStream out(&str,QIODevice::ReadWrite);  
    QString buf;
    while(!out.atEnd())
    {
          qint8 outChar = 0;
          out >> outChar;   
          QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper() + QString(" "); 

          buf += str;
    }
    return buf;
}

    数据处理过程中需要解决的最重要的问题就是对通信格式的拆解。假设我定义了一种简单的通信格式,通信内容为“123456\n”,实际的意义是“12.3”和“45.6”两个数据,我设计的提取过程如下(注意这个步骤是在槽函数update中):

 if (showdata <= 39 && showdata >= 30)    //数字0~9
    {
        showdata -= 30;
        a[i++] = showdata;
    }
    else
    {
        i = 0;
        ...       //数组数据整理
    }

    简单来说处理步骤大概有三个:

     1. if中提取有效通信数据,(此处是123456,没有换行\n,依次存储到数组a中);
     2. else中判断一帧通信是否结束,(此处因为\n为无效数据,只要检测到非字符类型就表示一帧通信结束,i置0重新开始接收数据)
     3. 每完成一帧通信后就可以在else中对数组中的数据进行整理得到有效数据,(比如此处要得到12.3,便是a[0]*10+a[1]+a[2]*0.1)

     上述示例虽然简单,但这个方法可以应用到所有通信格式中,只要多增加一些值的判断即可。至此,上位机程序已经可以接收到串口中传来的各气象要素数据,如果想显示数据值,可以放置一些Label控件来显示。

猜你喜欢

转载自blog.csdn.net/fpgadesigner/article/details/74295083
今日推荐