線程+定時實現linux下的Qt串口編程

線程+定時實現linux下的Qt串口編程php

做者:lizzy115      時間:2010,5,14linux

說明:本設計採用的是線程+定時實現linux下的Qt串口編程,而非網上資料很是多的Qt編寫串口通訊程序全程圖文講解系列,由於Qt編寫串口通訊程序全程圖文講解系列是很好實現,那只是在windows下面的,但是在linux下面實現串口的通訊並不是如此,緣由在於QextSerialBase::EventDriven跟QextSerialBase::Polling這兩個事件的區別,EventDriven屬於異步,Polling屬於同步,在windows下面使用的是EventDriven很容易實現,只要有數據就會觸發一個串口事件,網上說linux下面須要的是Polling,但是仍是不行的,只要串口有數據的時候他會在QByteArray temp = myCom->readAll(); 這句一直讀取數據,沒能退出,直到斷掉串口的時候才能把接受到的串口數據經過ui->textBrowser->insertPlainText(temp);打印在界面上,一直沒能解決這個問題,因此只好採用線程+定時實現linux下的Qt串口編程進行設計。ios

1、安裝環境:編程

系統平臺:Ubuntu-8.04,內核2.6.24-27-generic,圖形界面小程序

2、軟件需求及下地地址:windows

Qt版本 qt-linux-SDK-4.6.2多線程

注意:此處使用的是qt-linux-SDK-4.6.2版本,編譯經過了,以後須要把他移植到qt-embedded-linux-opensource-src-4.5.3.tar.gz,經過qte編譯後移植到開發板中,採用的測試開發板爲Micro2440,app

下載地址:略異步

3、程序編寫過程ide

程序編程流程:

      先新建一個工程空白工程,再創建Ui文件,經過designer進行Ui界面設計,設計完保存,編譯生成ui_mainwindow.h頭文件,編寫線程頭文件及線程處理.cpp文件,創建串口處理頭文件及 .cpp文件,最後完成main.cpp文件。

一、           Ui文件的設計:

創建Ui_MainWindow主窗口,在窗口上添加三個QPushButton,分別命名爲closeButton、writeButton、readButton,再添加一個QTextBrowser顯示串口接收數據,保存退出,編譯一下就能夠生成ui_mainwindow.h文件。

二、線程程序設計:

編寫一個線程程序,其不須要進行界面設計,直接實現線程的管理,實現串口的收發工做,其主要程序及說明以下:

1) 新建一個thread.h頭文件,內容以下:

#ifndef THREAD_H

#define THREAD_H

#include

class Thread:public QThread

{

Q_OBJECT

public:

Thread();

char buf[128];

volatile bool stopped;

volatile bool write_rs;

volatile bool read_rs;

protected:

virtual void run();

};

#endif

程序定義一個Thread類,它繼承於QThread,設有一些變量和一個run函數,virtual表示爲虛函數,你也能夠去掉,加上去會增長一些內存開銷,但提升了效率,對於這個小程序是看不出什麼效果的,volatile爲一函數數據類型,是一個類型修飾符(type specifier)。它是被設計用來修飾被不一樣線程訪問和修改的變量,其能夠在不一樣數據類型間進行轉化,保證對此變量的讀寫操做都不會被優化。若是沒有volatile,基本上會致使這樣的結果:要麼沒法編寫多線程程序,要麼編譯器失去大量優化的機會。

2)新建一個thread.cpp文件,內容以下:

#include"thread.h"

#include

#include

#include

#include     //串口用到的

#include

#include

#include

#include

#define BAUDRATE B9600

#define RS_DEVICE "/dev/ttyS0"       //串口1

//#define RS_DEVICE "/dev/ttySAC1"       //串口1

Thread::Thread()

{}                                                 //析構

void Thread::run()          //這就是線程的具體工做了

{

int fd,c=0,res;

struct termios oldtio,newtio; //termios結構是用來保存波特率、字符大小等

printf("start... ");

fd=open(RS_DEVICE,O_RDWR|O_NOCTTY);     //以讀寫方式打開串口。不控制TTY

if(fd<0)

{

perror("error");

exit(1);                             //失敗退出

}

printf("Open... ");

tcgetattr(fd,&oldtio);             //保存當前設置到oldtio

bzero(&newtio,sizeof(newtio));     //清除newtio結構,並從新對它的成員設置以下

newtio.c_cflag=BAUDRATE|CS8|CLOCAL|CREAD; //9600、8位、忽略DCD信號、啓用接收裝置

newtio.c_iflag|=IGNPAR;                    //忽略奇偶

newtio.c_oflag=0;

newtio.c_lflag=0;

newtio.c_cc[VMIN]=0;     

newtio.c_cc[VTIME]=100;     //在規定時間(VTIME)內讀取(VMIN)個字符;

tcflush(fd,TCIFLUSH);                //清除全部隊列在串口的輸入與輸出;

tcsetattr(fd,TCSANOW,&newtio);           //把咱們的設置寫入termios

while(stopped)                          //stopped爲0時將退出線程

{

if(write_rs)                        //write_rs爲1時把字符串從串口中輸出

{

write_rs=0;

write(fd,"QtEmbedded-4.5.3",16);

}

if(read_rs)                           //read_rs爲1時讀取,並存在buf

{

read_rs=0;

res=read(fd,buf,10);

buf[res]=0;

emit finished();                       //讀完後發一個信號

}

}

printf("Close... ");

tcsetattr(fd,TCSANOW,&oldtio);      //從新設置回原來的

close(fd);

quit();                           

}

經過stopped變量來實現線程控制。

三、主窗口程序設計:

主窗口程序包括線程的啓動與處理,經過信號與槽機制經過write按鍵實現寫串口,經過定時器實現讀串口操做,經過close按鍵實現串口關閉,同時把讀取串口數據進行顯示,其主要程序及分析以下:

1)新建一個mainwindow.h頭文件,內容以下:

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include

#include"ui_mainwindow.h"    // ui_mainwindow.h 文件爲designer設計

mainwindow.ui文件後,通過make後會生成這個頭文件,

#include"thread.h"           //包含線程包頭文件

 

class MainWindow:public QMainWindow,public Ui::MainWindow //多繼承

{

Q_OBJECT

public:

MainWindow(QWidget *parent=0);

public slots:

void writeThread();

void readThread();

void closeThread();

void display();

private:

Thread *yy;

};

#endif

MainWindow繼承於QMainWindow和MainWindow,即多繼承,對於不是很複雜的程序,用多繼承是一個較好的方法,若是程序較複雜,建議用單繼承,具體緣由待進一步研究,呵呵。

2)新建一個mainwindow.cpp文件,實現程序內容以下:

#include"mainwindow.h"

 

MainWindow::MainWindow(QWidget *parent)

:QMainWindow(parent)

{

setupUi(this);

yy = new Thread;

yy->start();          //啓動線程

yy->stopped=1;        //初始化變量

yy->write_rs=0;

yy->read_rs=0;

QTimer *time = new QTimer(this);   //新建定時類

time->start(50);                    //50ms定時

connect(writeButton,SIGNAL(clicked()),this,SLOT(writeThread()));                           

//經過信號與槽實現按鍵按下進行寫串口操做

connect(time,SIGNAL(timeout()),this,SLOT(readThread()));

                      //定時溢出實現讀串口操做

connect(closeButton,SIGNAL(clicked()),this,SLOT(closeThread()));

connect(yy,SIGNAL(finished()),this,SLOT(display()));      //接收信號實現顯示

}

void MainWindow::display()

{

textBrowser->setText(yy->buf);   //讀到的數據在textBrowser l顯示

}

void MainWindow::writeThread() //寫數據線程槽函數

{

yy->write_rs=1;

}

void MainWindow::readThread()   //讀數據線程槽函數

{

yy->read_rs=1;

}

void MainWindow::closeThread() //中止槽函數

{

yy->stopped=0;

}

四、main.cpp函數程序設計:

#include

#include"mainwindow.h"

int main(int argc,char *argv[])

{

QApplication app(argc,argv);

MainWindow mw;

mw.show();

return app.exec();

}

這樣整個linux環境下線程+定時實現的Qt串口編程的程序所有實現,能夠經過串口發送,接收數據實現數據的測試。

相關文章
相關標籤/搜索