目录
一、前言
二、串口助手实现
2.1、串口
2.1.1、可用串口信息-QSerialPortInfo
2.1.2、打开串口-QSerialPort
2.1.3、串口发送接收信息
2.2、定时器-QTimer
2.3、常用属性类型转换(会更新)
2.4、子控件组规则命名优化
一、前言
这个是学习QT中实现的一个小项目——串口助手,这里是根据串口助手制作过程中所需要使用的类和插件制作的一个笔记,方便以后成为我们的技术库,很方便于我们日后开发! 串口助手模样:
二、串口助手实现
2.1、串口
2.1.1、可用串口信息-QSerialPortInfo
每学习一个类,我们都需要去查手册,查看它的成员还有使用前提,我们才能更好的使用起来:
说明需要添加:
函数原型:
QList<QSerialPortInfo> QSerialPortInfo::availablePorts()QList<qint32> QSerialPortInfo::standardBaudRates()
我们使用上面这个类的这两个函数就可以得到地电脑当前可使用的端口和波特率了,这里我们做个小demo将其打印出来:
#include <QSerialPortInfo>#include <QDebug> //显示可用的串口端口QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();for(QSerialPortInfo serialInfo : serialList)//遍历容器{qDebug() << serialInfo.portName();//打印可用的端口号ui->comboBox_serialNum->addItem(serialInfo.portName());//添加标签}//显示电脑可用的波特率QList<qint32> serialbotelv = QSerialPortInfo::standardBaudRates();for(qint32 serialbotelvInfo : serialbotelv)//遍历容器{qDebug() << serialbotelvInfo;}
运行结果:
2.1.2、打开串口-QSerialPort
使用一个串口需要配置很多参数,相同打开一个串口也需要提前配置好参数:
QSerialPort::QSerialPort(QObject *parent = nullptr)
用给定的父对象构造一个新的串行端口对象。
使用案例:
QSerialPort *serialPort;
serialPort = new QSerialPort(this);//为串口创建一个空间
构造好串口端口对象后,接下来就是配置参数了,配置参数的函数也不难找到,在类中的public Functions里面:找到函数后,再根据函数的参数找到对应自己组要的配置即可。
这里以配置数据位为代表:
bool setDataBits(QSerialPort::DataBits dataBits)
然后在看它的参数是DataBits类型,然后我们再去手册查找
找到公共类型点进去,找到自己要找的:
最后再根据代码逻辑实现即可:学习QT最重要的就是学会查手册
//1. 选择端口号serialPort->setPortName(ui->comboBox_serialNum->currentText());//2. 配置波特率serialPort->setBaudRate(ui->comboBox_boautrate->currentText().toInt());//3. 配置数据位serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_databit->currentText().toUInt()));//4. 配置校验位switch (ui->comboBox_jiaoyan->currentIndex()) {case 0:serialPort->setParity(QSerialPort::NoParity);break;case 1:break;serialPort->setParity(QSerialPort::EvenParity);case 2:serialPort->setParity(QSerialPort::MarkParity);break;case 3:serialPort->setParity(QSerialPort::OddParity);break;case 4:serialPort->setParity(QSerialPort::SpaceParity);break;default:serialPort->setParity(QSerialPort::UnknownParity);break;}//5. 配置停止位serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_databit->currentText().toUInt()));//6. 流控if(ui->comboBox_fileCon->currentText() == "None")serialPort->setFlowControl(QSerialPort::NoFlowControl);//7. 打开串口if(serialPort->open(QIODevice::ReadWrite)){qDebug() << "serial open success";}
运行结果:
2.1.3、串口发送接收信息
发送信息:
const char* sendData = ui->lineEditSendContext->text().toStdString().c_str();
serialPort->write(sendData);//串口发送信息
qDebug() << "SendOK" << sendData;//打印信息验证
ui->textEditRecord->append(sendData);//将发送的信息添加到历史记录文本里面
接收信息:
接收信息和单片机一样,有信息来了就会有一股“感觉”来临,这个“感觉”在QT中就是我们常用的信息了,我们要利用好这个感觉,感觉来了就处理!我们可以查看手册这个类的信息有哪些?
发现这个类中没有和接收信息相关的信息,所以我们要往上查,查他的父类(子承父业):
所以我们还是老套路,绑定信号和槽,声明定义槽函数: (这里就不展示槽的声明了)
//串口接收信号readyRead连接
connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_SerialData_readyToRead);//串口读取槽函数
void Widget::on_SerialData_readyToRead()
{QString revMessage = serialPort->readAll();qDebug() << "getMessage:"<< revMessage;ui->textEditRev->append(revMessage);//将接收的信息记录在文本上
}
2.2、定时器-QTimer
定时器和单片机中的定时器使用都是类似的,使用起来并不难,QT配合手册可以更灵活使用:
.h文件class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_checkBox_clicked();void on_checkBox_clicked(bool checked);private:Ui::Widget *ui;QTimer *timer;//定时器变量声明
};.c文件Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);timer = new QTimer(this);//为定时器创建一个空间connect(timer,&QTimer::timeout,[=](){//定时器信号与槽绑定qDebug() << "timer out!";//时间到了干什么});
}Widget::~Widget()
{delete ui;
}//按键按下定时器开始
void Widget::on_pushButton_clicked()
{timer->start(1000);
}
//按键按下定时器结束
void Widget::on_pushButton_2_clicked()
{timer->stop();
}
运行结果:
更多使用放方法可以查看手册:
2.3、常用属性类型转换(会更新)
QString String_data = "hello";//QString转const char*const char* char_data = String_data.toStdString().c_str();const char* char_data2 = String_data.toLocal8Bit().constData();//QString转int,其他整数类型也是使用类似函数转换String_data.toInt();//QString转Hex显示QByteArray qtmp = String_data.toUtf8(); //QString转QByteArrayqtmp = qtmp.toHex(); //QString转HEXString_data = QString::fromUtf8(qtmp); //QByteArray转QStringqDebug() << String_data;//HEX显示转QStringQString temp = String_data;QByteArray temp2 = String_data.toUtf8(); //QString转QByteArray转QStringQByteArray temp3 = QByteArray::fromHex(temp2);//由HEX返回原来本质String_data = QString::fromUtf8(temp3); //QByteArray转QStringqDebug() << String_data;
运行结果:
2.4、子控件组规则命名优化
在QT工作开发中我们难免会使用相同的子控件来执行大差不差的工作,比如实现一个小项目串口助手中这种情况,很多数量的按键都是实现相同的功能-发送
如果作为一个小白来说,我们肯定会使用大量的信号与槽来实现,一个按键对应一对信号与槽,这样就显的代码太过于臃肿了,为了简洁,可以使用通过给子控件规则命名配合事件的使用来简单化代码:
1.我们首先需要给子控件规则命名:
2.然后
注意:头文件中需要声明槽函数.c文件
QList<QPushButton *> buttons;
for(int i = 1; i <= 9; i++){QString btnName = QString("pushButton_%1").arg(i);//建立命名QPushButton* btn = findChild<QPushButton *>(btnName);//寻找子控件中QPushButton类中是否有btnNameif(btn){//如果有btn->setProperty("buttonId",i);//设置它的属性IDbuttons.append(btn);//统一绑定一个槽,然后在这个槽on_command_button_clicked里面进行处理connect(btn,SIGNAL(clicked()),this,SLOT(on_command_button_clicked()));}
}//槽处理
void Widget::on_command_button_clicked()
{QPushButton *btn = qobject_cast<QPushButton *>(sender());//查看谁是发送信号的按键if(btn){int num = btn->property("buttonId").toInt();//将它的属性ID转换出来QString lineEditName = QString("lineEdit_%1").arg(num);//根据ID找对应的横线文本QLineEdit *lineEdit = findChild<QLineEdit *>(lineEditName);if(lineEdit)ui->lineEditSendContext->setText(lineEdit->text());QString checkBoxName = QString("checkBox_%1").arg(num);//根据ID找对应的CheckboxQCheckBox *checkBox = findChild<QCheckBox *>(checkBoxName);if(checkBox)ui->checkBHexSend->setChecked(checkBox->isChecked());on_btnSendContext_clicked();//发送信息}
}