线程+定时实现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串口编程的程序所有实现,能够经过串口发送,接收数据实现数据的测试。