Linux&imx6ull 使用QT开发串口工具(完整版)
- 1.扫描串口
- 2.配置选项
- 3.打开串口
- 4.关闭串口
- 5.接收数据
- 6.发送数据
- 7.清空显示
这篇博客中讲到的东西可能在实际的开发中并不实用,但是这个属于学习阶段,会加强QT的学习已经达到触类旁通的效果
代码地址:
gitee下载
这次的代码主要是在Linux中使用QT实现串口通信,现在ubuntu上成功的实现,然后在移植到imx6ull开发板上面,作为我的第一个嵌入式应用
这次的.ui的文件我上传到我这个账号的资源下载,我的资源基本都是免积分下载的,大家有需要的可以自己下载,也可以自己设计自己的ui
UI文件下载链接
UI界面截图如下:
说一下命名,在用C++代码的时候,控件的命名要做到顾名思义,这样子写代码就会很流畅,我命名就是控件类型+下划线+控件作用
说一下开发需要完成的工作:
- 设计UI
- 扫描串口
- 配置选项
- 打开串口
- 关闭串口
- 接收数据
- 发送数据
- 数据缓冲清除
1.扫描串口
QT提供了一个串口信息类来获取电脑的串口信息
导入QT类: #include
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { QString showName = info.portName()+":"+info.description(); ui->box_portName->addItem(showName); }
说明:info.portName 是获取串口名,比如说在window下面是COM3,COM4;在Linux里面则是ttyUSB0,。
info.description() 是获取串口描述信息,比如说 是属于CH340串口还是属于其它类型的串口,可以根据这个判断是否加入串口选择的那个comboBox复选框
说明:在这里我的开发板上面串口设备是已经提前知道了:ttymxc2
2.配置选项
配置的话比较简单,主要是用到了comboBox控件,配置串口的时候串口类提供了对应的接口函数
serial->setDataBits(QSerialPort::Data8);serial->setParity(QSerialPort::NoParity);serial->setStopBits(QSerialPort::OneStop);serial->setFlowControl(QSerialPort::NoFlowControl);serial->setBaudRate(QSerialPort::Baud115200);
所以配置串口只要一步,获取comboBox的内容然后传入对应的配置函数
这里我直接是手动输入的
获取comboBox控件当前选择的内容的函数是:
comboBox_baud->currentText() ----->返回的是当前复选框内容的内容 返回值为QString
comboBox_baud->currentIndex() —>返回的值当前选中内容的ID,因为comboBox控件的每一个内容都会有一个ID。
那到底是什么时候开始配置串口参数呢?
那肯定是在打开串口成功的时候去配置,如果打开失败,也没有配置可言
3.打开串口
打开串口回调函数是由打开串口按钮被点击触发的。 当按钮的clicked事件被触发的时候,进行的操作为:打开串口、配置串口参数
首先要对按钮进行信号与槽的绑定
代码如下:
connect(ui->pushButton_open_uart,&QPushButton::clicked,this,&MainWindow::pushButton_open_uart_cb);
回调函数
if(ui->pushButton_open_uart->text()==tr(“open”))这个是判断按钮的文字,如果是open就进行打开串口的操作,如果是close那就是进行串口关闭,这个也是用标志信息来实现按钮多用的效果
serial->setPortName("/dev/ttymxc2"); 设置串口名字
if(serial->open(QIODevice::ReadWrite)) 尝试打开串口读写服务,如果打开成功则开始配置串口参数,如果打开失败,则退出
comboBox_baud->setEnabled(false) 的意思是如果串口能够正常打开串口,那就是把串口参数的comboBox的全部失能
关闭串口:serial->close();
void MainWindow::pushButton_open_uart_cb(){ qDebug()<<"pushButton_open_uart_cb is running!"; if(ui->pushButton_open_uart->text()==tr("open")) { qDebug()<<ui->pushButton_open_uart->text(); serial = new QSerialPort; serial->setPortName("/dev/ttymxc2"); if(serial->open(QIODevice::ReadWrite)) { qDebug() << "open uart succ"; //如果串口打开成功,则开始配置串口参数 serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); serial->setBaudRate(QSerialPort::Baud115200); connect(serial, &QSerialPort::readyRead, this, &MainWindow::read_data_rb); ui->comboBox_baud->setEnabled(false); ui->comboBox_port->setEnabled(false); ui->comboBox_databit->setEnabled(false); ui->comboBox_stopbit->setEnabled(false); ui->comboBox_checkbit->setEnabled(false); ui->pushButton_open_uart->setText("close"); ui->label_state->setStyleSheet(this->state_red_SheetStyle); } } else { serial->clear(); serial->close(); serial->deleteLater(); qDebug() << "close uart succ"; ui->comboBox_baud->setEnabled(true); ui->comboBox_port->setEnabled(true); ui->comboBox_databit->setEnabled(true); ui->comboBox_stopbit->setEnabled(true); ui->comboBox_checkbit->setEnabled(true); ui->pushButton_open_uart->setText("open"); ui->label_state->setStyleSheet(this->state_grey_SheetStyle); }}
4.关闭串口
serial->close();可以进行串口的关闭
5.接收数据
其实串口接收数据是很有说法的。我知道的方法就是在主线程中接收和另外开辟一个线程进行数据的接收,后者的话需要自定义信号的槽
在这里我是在主线程中使用串口类提供的信号和槽进行接收
首先得绑定一下相关的信号与槽
这里的绑定是在打开串口成功(串口配置之后)之后再绑定的,这里需要注意一下
connect(serial, &QSerialPort::readyRead, this, &MainWindow::read_data_rb);
说明:QT的QSerialPort类提供了一个信号:readyRead,当这个串口有数据要读的时候,会触发这个信号,我们只需要将我们的接收回调函数read_data_rb() 做为readyRead信号的槽函数
读取数据可以使用QT串口类提供的一个接口函数 :buf = serial->readAll();
注意:这里返回值是一个字节流QByteArray的数据,而不是字符串
以前在写python的时候也是字节流,所以估计应该都是一样的,这就意味着需要进行解码才行
使用以下进行解码(要包含QTextCodec头文件)
QString str;
QTextCodec *codec = QTextCodec::codecForName(“GBK”);//指定QString的编码方式
QString str_buf=codec->toUnicode(buf);//buf转换成QString类型
选择ASCII HEX显示
判断radioButton的状态 可以使用isChecked函数判断某个radiobutton是否被选择,一个组里面的所有radiobutton只能有一个被选中,所以在设计UI的时候,就先把ASCII的radiobutton勾上了,表示默认是ASCII显示,
用以下代码进行选择HEX显示,直接用QByteArray的toHex函数即可
if(ui->radioButton_recv_hex->isChecked() == true)
{
buf=buf.toHex(); //或者使用这句话将buf转换成十六进制显示
str_buf=tr(buf);
}
添加到显示文本框:ui->apend
append函数是默认自动换行的,所以不用刻意的自己拼接一个换行符进去
rowser_recv->append(str_buf);
还有一个问题需要注意一下:接收显示完之后需要把接收缓冲区清零,否则下一次将会出现意外
回调函数代码如下:
void MainWindow::read_data_rb(){ QByteArray buf; buf = serial->readAll(); if(!buf.isEmpty()) { QString str; QTextCodec *codec = QTextCodec::codecForName("GBK");//指定QString的编码方式 QString str_buf=codec->toUnicode(buf);//buf转换成QString类型 if(ui->radioButton_recv_hex->isChecked() == true) { buf=buf.toHex(); //或者使用这句话将buf转换成十六进制显示 str_buf=tr(buf); } ui->textBrowser_recv->append(str_buf); this->recvByte_count = this->sendByte_count + str_buf.length(); QString send_count_str = QString::number(this->recvByte_count); ui->label_recvbyte_count->setText(send_count_str); } buf.clear();}
6.发送数据
发送数据的第一步肯定是要把发送按钮的信号和槽函数绑定好。在界面初始化的时候就可以进行绑定了
代码如下:
connect(ui->pushButton_send_data,&QPushButton::clicked,this,&MainWindow::pushButton_send_data_cb);
我们看一下回调函数的实现:
发送数据可以使用QT串口类提供的write接口函数:
serial->write(ui->textEdit_send->toPlainText().toLatin1());
其中toLatin1:是将输入内容的进行ASCII编码
if(ui->checkBox_send_linefeed->isChecked()==true) 判断换行发送是否被勾中,如果被勾中则会在发送完数据之后,再发送一个换行符serial->write("\n");
void MainWindow::pushButton_send_data_cb(){ serial->write(ui->textEdit_send->toPlainText().toLatin1()); if(ui->checkBox_send_linefeed->isChecked()==true) { serial->write("\n"); } QString send_buff = ui->textEdit_send->toPlainText(); this->sendByte_count = this->sendByte_count + send_buff.length(); QString send_count_str = QString::number(this->sendByte_count); ui->label_sendbyte_count->setText(send_count_str);}
7.清空显示
到这里,大部分的开发工作已经完成了,后面的所有操作都是锦上添花。
清空显示就是绑定、清空 就两步,特别简单
connect(ui->pushButton_clean_recv_buff,&QPushButton::clicked,this,&MainWindow::pushButton_clean_recv_buff_cb); connect(ui->pushButton_clean_input,&QPushButton::clicked,this,&MainWindow::pushButton_clean_input_cb);
槽函数
void MainWindow::pushButton_clean_input_cb(){ ui->textEdit_send->clear();}void MainWindow::pushButton_clean_recv_buff_cb(){ ui->textBrowser_recv->clear();}
够简单!
到这里基本就差不多了,后续的话可以添加一下其它的东西,例如:发送接收字节统计,发送文件,线程接收等等,反正做这种东西不是说要应用到实际,因为这些东西成品实在是太多了。作为初学者,通过写小工具,可以学到很多东西,这是一个学习的过程。授人以鱼不如授人以渔。下一篇还会更新其它的QT小工具开发。源码的话,过一两天整理好会把GitHub、gitee、CSDN的下载链接放上来。(编译器使用的是Linux里面64位的QT creator下载的时候里面的64位编译器,如果用其它的编译器,那就复制源码,到自己的工程编译就行,或者去修改编译器选项)
冲!