让串口可以自动分辨一帧数据
有時我們希望串口接收到數據后,在該幀數據的末尾加上一些標志,比如這是第幾幀或接收的時間等等。那么我們就需要知道什么時候
接收到了完整的一幀數據。有兩種方法可以實現:
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也沒幾日,上面難免會出現不地道的語句,希望大家別見笑。另外,這個發帖子的東東我也是第一次用,發的帖子不是很好,以后慢慢學習。另外希望大家一起進步。
總結
以上是生活随笔為你收集整理的让串口可以自动分辨一帧数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习实战之SVM
- 下一篇: windows下安装django的一些问