让串口可以自动分辨一帧数据

串口接收完整一帧数据处理方式

有时我们希望串口接收到数据后,在该帧数据的末尾加上一些标志,比如这是第几帧或接收的时间等等。那么我们就需要知道什么时候

接收到了完整的一帧数据。有两种方法可以实现:

1,自己人为地在一帧数据的最后加上一个标志符号,如#,@等,上位机接收到这些标志后可认为一帧数据到来完成。这样做很方便,但缺点是

    只能分辨自己做好的数据,对于别人做的设备的信号监控做不到分割

2:利用定时器判断一帧数据是否完成。这种做法可以通用与任何信息。

下面主要分析第二种方法,对第一种方法感兴趣的朋友可以自己实验。以波特率9600BPS为例。

9600BPS,则传送每一位的时间为1000MS/9600=0.104MS,即位与位之间间隔为0.104MS,

现在假如我们在操作PC机最底层IO,收到5个数据。当5个数据的第一个数据到来时,我们启动一个

定时器,时间为1MS,然后每收到一个数据时就重新设置定时器,因为0.104MS要远远小于1MS,所以

如果一直有数据来,定时器就会被重设,没有溢出的机会。当没有数据来了(也就是第5个数据接收到了)

定时器不会被重设直到溢出产生事件号,然后我们就到这个事件号的处理函数里面处理刚接收的完整的一帧数据了

,当然该处理函数里面要停止定时器,直到再有数据来才开启。本人不善言辞,不直到讲的大家听懂没有。

下面弄点实际的东东给大家看,我是把yafeilinux 老兄的串口稍加修改做成,如果刚看到我的例子的朋友

可以先看看他写的串口(Qt编写串口通信程序全程图文讲解),写的很好很容易懂。

头文件中增加如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>
#include <QTimer>//添加定时器类
#include <QtCore>//添加日期类
#include <QString>
#include “win_qextserialport.h”

namespace Ui
{
    class MainWindow;
}

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    void changeEvent(QEvent *e);

private:
    Ui::MainWindow *ui;
    Win_QextSerialPort *myCom;

 //增加一个数据用于放数据
    char data[1024];               

//增加一个标志用于计算接收了个多少数据        
    unsigned int bytesRead ;       
    QTimer *timer;

private slots:
    void on_sendComMsgbtn_released();
    void on_closeMyCombtn_released();
    void on_openMyCompbn_released();

// 增加一个函数用于定时器溢出后的处理程序
    void timerUpDate();
    void readMyCom();
};

#endif // MAINWINDOW_H

然后是.cpp文件

#include “mainwindow.h”
#include “ui_mainwindow.h”

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->openMyCompbn->setEnabled(true);
    ui->closeMyCombtn->setEnabled(false);
    ui->sendComMsgbtn->setEnabled(false);
    bytesRead = 0;
    timer = new QTimer(this);

    connect(timer,SIGNAL(timeout()),this,SLOT(timerUpDate()));
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MainWindow::readMyCom()
{
    unsigned int byte = 0;
    byte = myCom->read(&data[bytesRead], 1024);
    bytesRead +=byte;

//上面讲的就在此体现了,为什么是50呢,因为此是并不是操作最底层IO,PC机会将数据接收几个后在给上层。所以这个时间稍微长一点点
    timer->start(50);

}
void MainWindow::on_openMyCompbn_released()
{
   
    struct PortSettings myComSetting = {BAUD9600,DATA_8,PAR_NONE,STOP_1,FLOW_OFF,
                                    500};
    myCom = new Win_QextSerialPort(“com1″,myComSetting,QextSerialBase::EventDriven);
   if( myCom->open(QIODevice::ReadWrite))
    {
    connect(myCom,SIGNAL(readyRead()),this,SLOT(readMyCom()));
    ui->openMyCompbn->setEnabled(false);
    ui->closeMyCombtn->setEnabled(true);
    ui->sendComMsgbtn->setEnabled(true);
    }
   else
   {
       QMessageBox::information(this,tr(“错误”),tr(“串口被打开或没有该串口”));
   }
}

void MainWindow::on_closeMyCombtn_released()
{
    myCom->close();
    ui->openMyCompbn->setEnabled(true);
    ui->closeMyCombtn->setEnabled(false);
    ui->sendComMsgbtn->setEnabled(false);
}

void MainWindow::on_sendComMsgbtn_released()
{
    myCom->write(ui->sendMsglineEdit->text().toAscii());
}

//定时器到的处理函数,我在数据的最好添加了一帧日期。刚看这里的朋友也可以看看yafeilinux讲的关于定时器和日期(十、Qt Creator中实现定时器和产生随机数)的文章
void MainWindow::timerUpDate()
{
    timer->stop();
    QDateTime time = QDateTime::currentDateTime();
    QString str = time.toString(“yyyy-MM-dd hh:mm:ss dddd”);
    ui->textBrowser->insertPlainText(str.append(‘n’));
    data[bytesRead] = ‘n’;
    data[bytesRead+1] = ”;
    ui->textBrowser->insertPlainText(data);
    bytesRead = 0;
}

好了,讲到这了,本人才疏学浅,学QT也没几日,上面难免会出现不地道的语句,希望大家别见笑。另外,这个发帖子的东东我也是第一次用,发的帖子不是很好,以后慢慢学习。另外希望大家一起进步。

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值