由于某项目需要,需要写一个处理串口数据的程序,之前也没有用过Qt,所以这次打算用Qt实现这个功能。
有一说一,Qt相比于MFC真的是方便快捷了很多,在开发界面的方面还是很强大的。
话不多说,先上咱们最终实现的效果图。界面简单,如果大家在某些地方需要通过串口获取数据之后做处理的话,可以考虑使用。
通过点击按钮从串口读取数据并展现到文本框中。
功能是能够实现获取串口数据最简单的一些基础功能,肯定是不能和网上下载的很多成熟的软件比较,就比如微软自带的串口调试助手,如下图:
除了能够实现读取数据的同时,还能够设置额外输出方式等等算是额外辅助的功能吧。
实现的步骤按照如下几个步骤展开讲解:
对于串口的读取,Qt中自带了两个类供我们使用,分别是QtSerialPort、QserialPortInfo,基础对串口的操作这两个类都是提供了的。兄弟们如果在这个基础上加功能可以查询一下这两个类,根据这两个类里面自带的函数扩充你想要的功能。
1、首先就是在.pro文件中加上serialport,熟悉Qt的小伙伴一定都知道在Qt中使用什么额外的功能呀什么的,就要在这个部分写上这句话。
QT += core gui serialport
2、对界面上的一些空间初始化
对于界面中控件的一些命名什么的,大家可以看下面的代码,通过变量名大家可以很容易得到控件的命名信息。这里就不详细给兄弟们展示了。
//设置串口初始化状态 ReadSerialPort = NULL; //设置界面初始的状态 ui->ReadBtn->setEnabled(true); ui->StopReadBtn->setEnabled(false); //初始化串口设置部分 ui->ChooseComComboBox->clear(); ui->ChooseBoudComboBox->clear(); ui->ChooseDataBitsComboBox->clear(); ui->ChooseParityComboBox->clear(); ui->ChooseStopComboBox->clear(); QStringList ChooseComList; QStringList ChooseBoudList; QStringList ChooseDataBitsList; QStringList ChooseParityList; QStringList ChooseStopList; //获取电脑连接的串口信息供选择 foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) { ChooseComList << info.portName(); } ui->ChooseComComboBox->addItems(ChooseComList); ui->ChooseComComboBox->setCurrentIndex(0); //波特率的选择 ChooseBoudList <<"1200" <<"2400" <<"4800" <<"9600" <<"19200" <<"38400" <<"57600" <<"115200"; ui->ChooseBoudComboBox->addItems(ChooseBoudList); ui->ChooseBoudComboBox->setCurrentIndex(0); //数据位的选择 ChooseDataBitsList <<"5" <<"6"<<"7"<<"8"<<"UnknownDataBits"; ui->ChooseDataBitsComboBox->addItems(ChooseDataBitsList); ui->ChooseDataBitsComboBox->setCurrentIndex(0); //校验位的选择 ChooseParityList <<"NoParity" <<"EvenParity" <<"OddParity" <<"UnknownParity"; ui->ChooseParityComboBox->addItems(ChooseParityList); ui->ChooseParityComboBox->setCurrentIndex(0); //停止位的选择 ChooseStopList <<"1" <<"2" <<"无"; ui->ChooseStopComboBox->addItems(ChooseStopList); ui->ChooseStopComboBox->setCurrentIndex(0);
3、连接串口功能的实现。这也是最核心的部分:
//点击按钮之后把状态改变了 ui->ReadBtn->setEnabled(false); ui->StopReadBtn->setEnabled(true); //每次点击按钮之后创建一个对象,这也是解决了之前读取空值的问题 ReadSerialPort = new QSerialPort(); if(ReadSerialPort->isOpen())//如果串口已经打开了 先给他关闭了 { ReadSerialPort->clear(); ReadSerialPort->close(); } //根据下拉框选取串口 QString ChoosedPortName=ui->ChooseComComboBox->currentText(); ReadSerialPort->setPortName(ChoosedPortName);//当前选择的串口名字 if(ReadSerialPort->open(QIODevice::ReadWrite))//用ReadWrite 的模式尝试打开串口 { ReadSerialPort->setDataTerminalReady(true); //根据下拉框选择波特率 qint32 BaudrateIndex = ui->ChooseBoudComboBox->currentIndex(); switch (BaudrateIndex) { case 0: ReadSerialPort->setBaudRate(QSerialPort::Baud1200); break; case 1: ReadSerialPort->setBaudRate(QSerialPort::Baud2400); break; case 2: ReadSerialPort->setBaudRate(QSerialPort::Baud4800); break; case 3: ReadSerialPort->setBaudRate(QSerialPort::Baud9600); break; case 4: ReadSerialPort->setBaudRate(QSerialPort::Baud19200); break; case 5: ReadSerialPort->setBaudRate(QSerialPort::Baud38400); break; case 6: ReadSerialPort->setBaudRate(QSerialPort::Baud57600); break; case 7: ReadSerialPort->setBaudRate(QSerialPort::Baud115200); break; default: ReadSerialPort->setBaudRate(QSerialPort::UnknownBaud); break; } //根据下拉框选择数据位 qint32 DatabitsIndex=ui->ChooseDataBitsComboBox->currentIndex(); switch (DatabitsIndex) { case 0: ReadSerialPort->setDataBits(QSerialPort::Data5); break; case 1: ReadSerialPort->setDataBits(QSerialPort::Data6); break; case 2: ReadSerialPort->setDataBits(QSerialPort::Data7); break; case 3: ReadSerialPort->setDataBits(QSerialPort::Data8); break; default: ReadSerialPort->setDataBits(QSerialPort::UnknownDataBits); break; } //根据下拉框选择校验位 qint32 ParityIndex=ui->ChooseParityComboBox->currentIndex(); switch (ParityIndex) { case 0: ReadSerialPort->setParity(QSerialPort::NoParity); break; case 1: ReadSerialPort->setParity(QSerialPort::EvenParity); break; case 2: ReadSerialPort->setParity(QSerialPort::OddParity); break; default: ReadSerialPort->setParity(QSerialPort::UnknownParity); break; } //根据下拉框选择停止位 qint32 StopbitIndex=ui->ChooseStopComboBox->currentIndex(); switch (StopbitIndex) { case 0: ReadSerialPort->setStopBits(QSerialPort::OneStop); break; case 1: ReadSerialPort->setStopBits(QSerialPort::TwoStop); break; default: ReadSerialPort->setStopBits(QSerialPort::UnknownStopBits); break; } //实例 误删 //ReadSerialPort->setBaudRate(QSerialPort::Baud115200);//设置波特率和读写方向 //ReadSerialPort->setDataBits(QSerialPort::Data8); //数据位为8位 //ReadSerialPort->setFlowControl(QSerialPort::NoFlowControl);//无流控制 //ReadSerialPort->setParity(QSerialPort::NoParity); //奇校验位 //ReadSerialPort->setStopBits(QSerialPort::OneStop); //两位停止位 ReadSerialPort->clearError(); ReadSerialPort->clear(); connect(ReadSerialPort,&QSerialPort::readyRead,this,&Read::receiveInfo);
这里说一下之前自己遇到的一个问题吧,原本我的QT版本是5.13.0,当时代码已经调整过了,但是无论怎样都无法获取到串口传过来的值,这个bug改了整整一天,后来发现是QT这个版本的问题,后来把这个版本卸载然后装上了5.14.2,问题直接解决。
当然这里要提一下还有另外一个方式可以解决这个问题,就是通过添加waitForReadyRead(30000);这个方式倒是也解决了读取的问题,但是后面遇到了其他的的问题,可能是因为我当时想着使用线程的原因,导致的程序崩溃的问题,但是具体是不是因为这句话我就不知道了,但是换了版本之前的问题迎刃而解。我这里还是建议大家直接安装一个没有问题的版本吧,后面会省去很多的事情。
4、输出数据实现
void Read::receiveInfo() { //读取串口的数据并且把数据转换成字符串类型 QByteArray info = ReadSerialPort->readAll(); qDebug() << info; ui->GpsOutputTextEdit->append(info); }