基于Qt5.6做一个最简单的具有收发功能的串口助手

来源:互联网 发布:简谱制作软件app 编辑:程序博客网 时间:2024/05/18 02:52

最近由于实验室面试需要,开始对Qt有了一些接触,也开始尝试一些自己认为近阶段不可能做的东西。 
实验室安排的打怪兽的任务是做一个界面,接收串口数据打印成波形,那最做的就是先解决串口数据收发的问题,于是开始着手上网学习各种资料,最终也做出了一个比较稳定的串口助手,这里讲的也只关于串口助手的程序实现。

在Qt中要写界面,得先新建一个项目,打开Qt,选择菜单栏上的文件 选项,新建文件或项目 ,新建一个界面应用,选择Application ,然后右边选择Qt Widgets Application

新建应用界面

然后为项目命名,选择项目文件存放的位置:

项目命名

接着下一步默认就行了,应为系统已经默认为项目选择了编译器,调试器等等:

下一步

接着选择一个基类,我这里选的是QWidget,选择后,头文件,资源文件什么的都会自动以基类名称命名:

选择基类

然后再下一步,版本控制不用管它,直接下一步,然后就可以写代码了。

写代码前,先了解一下Qt5之后版本自带有串口类,之前的Qt版本不自带有串口类,做串口相关界面时主要用到了第三方的类库,但现在Qt自带了,用起来也方便很多, 
主要用到QtSerialPort模块中的两个类:一个是QSerialPort,另一个是QSerialPortInfo。 
QSerialport 提供了各种操作串口的接口 
QSerialportInfo 提供计算机中可用串口的各种信息 
若在程序中要用到这些串口类,需要在pro文件中添加:

 QT       += serialport
  • 1
  • 1

pro

然后在用到串口类的文件中包含两个头文件:

#include <QtSerialPort/QSerialPort>#include <QtSerialPort/QSerialPortInfo>
  • 1
  • 2
  • 1
  • 2

后面会用到QTimer(用于计时)和QDebug(用于输出一些调试信息)前,所以在用到这两个的时候得先包含以下这两个头文件:

#include <QTimer>#include <QDebug>
  • 1
  • 2
  • 1
  • 2

一、

第一步先准备下界面,双击界面ui文件

打开界面文件

然后向界面编辑区里分别拖入以下几个控件:两个ComboBox,两个Label,两个PushButton,一个LineEdit,一个TextEidt。 
PushButon和Label可以直接双击其表面,对表面的文字进行修改。控件的大小也可以进行修改。

拉入控件的界面

上面那个大的是textEdit。

然后在界面右边有一个对象属性编辑器,可以对对象属性进行修改。例如修改名字(在objectName那修改对象的名字):

对象属性编辑

将上面那个ComboBox名字改成comboBox_portName用于显示打开的端口号。 
下面那个ComboBox名字改成comboBox_baudRate 用于显示波特率。 
TextEdit名字改成textEdit_read 用于显示串口读取到的信息。 
LineEdit名字改成lineEdit_write 用于写入要发送给串口的信息。 
发送数据数据的那个PushButton名字改成pushButton_send 用于控制发送数据。 
打开串口的那个PushButton名字改成pushButton_comopen 用于打开串口。

然后双击显示波特率的那个ComboBox,按下面那个+按钮,添加几个波特率:

添加波特率

界面基本就这样,接下来是各个控件功能的实现。

二、

界面弄好后,按下编辑回到文件编辑区:

编辑

双击打开头文件,我这里是widget.h

widget.h

在里面包含下面三个头文件:

三个头文件

Widget类中的private下面添加:

QSerialPort *my_serialPort;//(实例化一个指向串口的指针,可以用于访问串口)QByteArray requestData;//(用于存储从串口那读取的数据)QTimer *timer;//(用于计时)
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

实例化三个对象

然后双击源文件中的widget.cpp对其进行编辑:

widget.cpp

现在顶部添加开头提到的那四个头文件:

添加四个头文件

构造函数里进行一些初始初始工作

构造函数

添加:

foreach( const QSerialPortInfo &Info,QSerialPortInfo::availablePorts())//读取串口信息    {        qDebug() << "portName    :"  << Info.portName();//调试时可以看的串口信息        qDebug() << "Description   :" << Info.description();        qDebug() << "Manufacturer:" << Info.manufacturer();        QSerialPort serial;        serial.setPort(Info);        if( serial.open( QIODevice::ReadWrite) )//如果串口是可以读写方式打开的        {            ui->comboBox_portName->addItem( Info.portName() );//在comboBox那添加串口号            serial.close();//然后自动关闭等待人为开启(通过那个打开串口的PushButton)        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这里写图片描述

然后双击界面文件回到界面编辑区

右键点击“打开串口”那个PushButton,点击转到槽,双击click()信号会自动转到widget.cpp中进行槽编辑

这里写图片描述

这里写图片描述

在里面可以对点击那个按钮的作用进行编辑

添加:

    //对串口进行一些初始化        my_serialPort = new QSerialPort(this);        my_serialPort->setPortName( ui->comboBox_portName->currentText() );        my_serialPort->open( QIODevice::ReadWrite );        qDebug() << ui->comboBox_portName->currentText();        my_serialPort->setBaudRate(  ui->comboBox_baudRate->currentText().toInt() );//波特率        my_serialPort->setDataBits( QSerialPort::Data8 );//数据字节,8字节        my_serialPort->setParity( QSerialPort::NoParity );//校验,无        my_serialPort->setFlowControl( QSerialPort::NoFlowControl );//数据流控制,无        my_serialPort->setStopBits( QSerialPort::OneStop );//一位停止位        timer = new QTimer(this);        connect( timer, SIGNAL( timeout() ), this, SLOT( readMyCom() ) );        timer->start(1000);//每秒读一次
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这里写图片描述

一样的回到界面编辑那,右键点击发送数据那个PushButton,选择转到槽,双击click()信号:(对发送数据那个按钮的功能进行实现)

添加:

  my_serialPort->write( ui->lineEdit_write->text().toUtf8() );
  • 1
  • 1

这里写图片描述

然后转到widget.h 
看到private slots下面,相信那里现在已经有两个信号槽函数的声明: 
在那在添加一个

void readMyCom();//用于读取数据
  • 1
  • 1

这里写图片描述

回到widget.cpp

在刚刚我们编辑过槽函数下面对readMyCom()进行实现: 
添加:

void Widget::readMyCom()//读取缓冲的数据,每秒读一次{    requestData = my_serialPort->readAll();//用requestData存储从串口那读取的数据    if(requestData!=NULL)//如果读取到有数据,就显示出来。    {        ui->textEdit_read->append(requestData);    }    requestData.clear();    //清除缓冲区}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这样一个最简单的串口助手就做出来了,

这里写图片描述

一定要在确定打开了串口后,再发送过数据,不然程序会崩溃。 
若串口打开了,会在程序输出那里输出串口号的 (这是前面说的那个qDebug()的作用):

这里写图片描述

记住,这只是一个最简单不过的串口助手,还需要对其进行一步步改进才能使其在使用过程中保持稳定而不容易崩溃。你得根据在平时使用时可能进行的一些错误操作对其进行一步步的修改、改进,使其越来越稳定;也可以根据自己进行串口操作时可能需要用到的功能自己进行实现,使它的功能越来越丰富。这样渐渐形成一个具有丰富功能和强稳定性的串口助手。 
我自己做出来的基本上这样。

这里写图片描述

这里贴一个我做出来的串口助手的连接吧。

串口助手

0 0