Qt串口通信专题教程查看以前的教程:Qt编写串口通信程序全程图文讲解查看Wincom和Lincom介绍:Qt跨平台串口通信软件Wincom与Lincom下载软件,文档和源码:资源下载——————————————2010年7月8日更新——————————————–网友赵文杰使用多线程完成的linux下的串口通信。下载源码:下载—————————————————————————————————————以下是正文:前言去年我使用Qt编写串口通信程序时,将自己的学习过程写成了教程(Qt编写串口通信程序全程图文讲解),但是由于时间等原因,我只实现了Windows下的串口通信,并没有去做Linux下的。自从教程发布到网上后,就不断有人提出相关的问题,而其中问的最多的就是,怎样在Linux下实现串口通信。因为有计划安排,而且没有开发板,所以一直没能去研究,也就没能给出很好的解决办法。前些天,网友hqwfreefly用Qt写了一个叫linucom的Linux下串口调试程序,实现了Linux的串口通信。而且,正好现在我有几天假期,所以就和hqwfreefly合作,将linucom更新为Lincom,并且推出了Windows下的Wincom,然后完成了这篇Qt编写串口通信程序的专题教程,也算完成了我的一个心愿。教程概述该教程分三部分讲述,第一部分讲解qextserialport类的一些东东;第二部分讲解在Windows下使用qextserialport类实现串口通信的方法,这里将讲述两种不同的方法;第三部分讲解在Linux下利用qextserialport类实现串口通信的方法。在这个教程中我们更注重知识的讲解,而不是界面的设计。关于界面和其他应用问题,你可以查看以前的串口通信教程或者查看一下Wincom软件的源码。第一部分Qextserialport类介绍在Qt中并没有特定的串口控制类,现在大部分人使用的是第三方写的qextserialport类,我们这里也使用了该类。一、文件下载文件下载地址:也可以下载我上传到网盘上的:二、文件内容介绍1.下载到的文件为qextserialport-1.2win-alpha,解压并打开后其内容如下。(点击图片可以查看清晰大图)下面分别介绍:(1)doc文件夹中的文件内容是QextSerialPort类和QextBaseType的简单的说明,我们可以使用记事本程序将它们打开。(2)examples文件夹中是几个例子程序,可以看一下它的源码,不过想运行它们好像会出很多问题啊。(3)html文件夹中是QextSerialPort类的使用文档。(4)然后就是剩下的几个文件了。其中qextserialenumerator.cpp及qextserialenumerator.h文件中定义的QextSerialEnumerator类是用来获取平台上可用的串口信息的。不过,这个类好像并不怎么好用,而且它不是我们关注的重点,所以下面就不再介绍它了。(5)qextserialbase.cpp和qextserialbase.h文件定义了一个QextSerialBase类,win_qextserialport.cpp和win_qextserialport.h文件定义了一个Win_QextSerialPort类,posix_qextserialport.cpp和posix_qextserialport.h文件定义了一个Posix_QextSerialPort类,qextserialport.cpp和qextserialport.h文件定义了一个QextSerialPort类。这个QextSerialPort类就是我们上面所说的那个,它是所有这些类的子类,是最高的抽象,它屏蔽了平台特征,使得在任何平台上都可以使用它。2.几个类的简单介绍。下面是这几个类的关系图。可以看到它们都继承自QIODevice类,所以该类的一些函数我们也可以直接来使用。图中还有一个QextBaseType类,其实它只是一个标识,没有具体的内容,它用来表示Win_QextSerialPort或Posix_QextSerialPort中的一个类,因为在QextSerialPort类中使用了条件编译,所以QextSerialPort类既可以继承自Win_QextSerialPort类,也可以继承自Posix_QextSerialPort类,所以使用了QextBaseType来表示。这一点我们可以在qextserialport.h文件中看到。再说QextSerialPort类,其实它只是为了方便程序的跨平台编译,使用它可以在不同的平台上,根据不同的条件编译继承不同的类。所以它只是一个抽象,提供了几个构造函数而已,并没有具体的内容。在qextserialport.h文件中的条件编译内容如下:/*POSIXCODE*/#ifdef_TTY_POSIX_#include“posix_qextserialport.h”#defineQextBaseTypePosix_QextSerialPort/*MSWINDOWSCODE*/#else#include“win_qextserialport.h”#defineQextBaseTypeWin_QextSerialPort#endif所以,其实我们没有必要使用这个类,直接使用Win_QextSerialPort或Posix_QextSerialPort就可以了。当然如果你想使用这个类,实现同样的源程序可以直接在Windows和Linux下编译运行,那么一定要注意在Linux下这里需要添加#define_TTY_POSIX_。而我们这里为了使得程序更明了,所以没有使用该类,下面也就不再介绍它了。QextSerialBase类继承自QIODevice类,它提供了操作串口所必需的一些变量和函数等,而Win_QextSerialPort和Posix_QextSerialPort均继承自QextSerialBase类,Win_QextSerialPort类添加了Windows平台下操作串口的一些功能,Posix_QextSerialPort类添加了Linux平台下操作串口的一些功能。所以说,在Windows下我们使用Win_QextSerialPort类,在Linux下我们使用Posix_QextSerialPort类。3.在QextSerialBase类中还涉及到了一个枚举变量QueryMode。它有两个值Polling和EventDriven。QueryMode指的是读取串口的方式,下面我们称为查询模式,我们将Polling称为查询方式Polling,将EventDriven称为事件驱动方式。事件驱动方式EventDriven就是使用事件处理串口的读取,一旦有数据到来,就会发出readyRead()信号,我们可以关联该信号来读取串口的数据。在事件驱动的方式下,串口的读写是异步的,调用读写函数会立即返回,它们不会冻结调用线程。而查询方式Polling则不同,读写函数是同步执行的,信号不能工作在这种模式下,而且有些功能也无法实现。但是这种模式下的开销较小。我们需要自己建立定时器来读取串口的数据。在Windows下支持以上两种模式,而在Linux下只支持Polling模式。三、小结。这里讲了这么多,最后要说的只是,我们在Qt中使用这个类编写串口程序,根据平台的不同只需要分别使用四个文件。在Windows下是:qextserialbase.cpp和qextserialbase.h以及win_qextserialport.cpp和win_qextserialport.h在Linux下是:qextserialbase.cpp和qextserialbase.h以及posix_qextserialport.cpp和posix_qextserialport.h而在Windows下我们可以使用事件驱动EventDriven方式,也可以使用查询Polling方式,但是在Linux下我们只能使用查询Polling方式。第二部分在Windows下编写串口通信程序我们的环境是Windowsxp,Qt4.6.3及QtCreator2.0。第一,下面我们首先使用事件驱动来实现串口通信。1.新建工程。我们在QtCreator中新建QtGui工程,命名为myCom,BaseClass选择QWidget。2.添加文件。我们将那四个文件添加到工程文件夹中。如下图。然后我们将这四个文件添加到工程中,在QtCreator的工程列表中的工程文件夹上点击鼠标右键,在弹出的菜单中选择“AddExistingFiles”菜单。如下图。我们在弹出的对话框中选中四个文件,按下“打开”按钮即可,如下图。最终工程文件列表如下图。3.更改界面。我们将界面设计如下。其中的TextBrowser部件用来显示接收到的数据,LineEdit部件用来输入要发送的数据,PushButton按钮用来发送数据。我们保持各部件的属性为默认值即可。4.我们在widget.h文件中进行对象及函数声明。添加头文件包含:#include“win_qextserialport.h”然后在private中声明对象:Win_QextSerialPort*myCom;声明私有槽函数:privateslots:voidon_pushButton_clicked();//”发送数据”按钮槽函数voidreadMyCom();//读取串口5.在widget.cpp文件中进行更改。在构造函数中添加代码,完成后,构造函数内容如下:Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);myCom=newWin_QextSerialPort(“COM1″,QextSerialBase::EventDriven);//定义串口对象,指定串口名和查询模式,这里使用事件驱动EventDrivenmyCom-open(QIODevice::ReadWrite);//以读写方式打开串口myCom-setBaudRate(BAUD9600);//波特率设置,我们设置为9600myCom-setDataBits(DATA_8);//数据位设置,我们设置为8位数据位myCom-setParity(PAR_NONE);//奇偶校验设置,我们设置为无校验myCom-setStopBits(STOP_1);//停止位设置,我们设置为1位停止位myCom-setFlowControl(FLOW_OFF);//数据流控制设置,我们设置为无数据流控制myCom-setTimeout(500);//延时设置,我们设置为延时500ms,这个在Windows下好像不起作用connect(myCom,SIGNAL(readyRead()),this,SLOT(readMyCom()));//信号和槽函数关联,当串口缓冲区有数据时,进行读串口操作}实现槽函数:voidWidget::readMyCom()//读取串口数据并显示出来{QByteArraytemp=myCom-readAll();//读取串口缓冲区的所有数据给临时变量tempui-textBrowser-insertPlainText(temp);//将串口的数据显示在窗口的文本浏览器中}voidWidget::on_pushButton_clicked()//发送数据{myCom-write(ui-lineEdit-text().toAscii());//以ASCII码形式将数据写入串口}6.此时,我们运行程序,效果如下。可以看到,已经成功完成通信了。(注:我们这里下位机使用的是单片机,它使用串口与计算机的COM1相