QT 串口编程 ESP8266

界面:

1、

 

 

 2、原理图,现在做的就是红字描述的东西

3、常用AT指令中,Label标签(就是那个闪电符号的东西)没有点击信号,所以需要自定义控件,Label标签要与对应的QLineEdit建立伙伴关系。创建一个TMyLabel的C++类,继承QLabel类,在TMyLabel类中自定义clicked()信号。

        通过串口给ESP8266发送AT指令,可以通过简单的文本通信方式控制和配置模块,实现与Wi-Fi网络、远程服务器和其他设备的通信与交互。

TMyLabel.h

#ifndef TMYLABEL_H
#define TMYLABEL_H

#include <QLabel>
#include <QObject>

class TMyLabel : public QLabel
{
    Q_OBJECT
protected:
    void mousePressEvent(QMouseEvent *event);
public:
    TMyLabel(QWidget *parent = nullptr);

signals:
    void clicked();
};

#endif // TMYLABEL_H

 TMyLabel.cpp

#include "tmylabel.h"


#include <QMouseEvent>

void TMyLabel::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        emit clicked();
    event->accept();
}

TMyLabel::TMyLabel(QWidget *parent):QLabel(parent)
{

}

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QList>
#include "tmylabel.h"
#include <QSettings>
#include <QMessageBox>
#include <QElapsedTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    QSerialPort comPort;                //串口对象
    void uartSend(QString cmd);         //向串口发送字符串数据
    void delayMs(int ms);               //毫秒级延时
    void loadFromReg();                 //从注册报表载入界面数据
    void saveToReg();                   //保存到注册表
    void closeEvent(QCloseEvent *event);

public slots:
    void do_com_readyRead();            //串口有数据可读
    void do_label_clicked();            //与TMyLabel组件的clicked()信号关联
    void on_actCom_Open_triggered();
    void on_actCom_Close_triggered();
    void on_btnWF_UART_Qry_clicked();
    void on_btnWF_Reset_clicked();
    void on_btnWF_Test_clicked();
    void on_btnWF_UART_Set_clicked();
    void on_btnTrans_Exit_clicked();
    void on_btnTrans_Enter_clicked();
    void on_btnTCP_GetMac_clicked();
    void on_btnWF_GetAP_clicked();
    void on_btnTCP_Query_clicked();
    void on_btnWF_SetAsSTA_clicked();
    void on_btnWF_SetAP_clicked();
    void on_btnTCP_SetServer_clicked();
    void on_pushButton_4_clicked();
    void on_btnTrans_AutoOnReset_clicked();
    void on_btnNormSend_clicked();
    void on_btnTCP_AutoConn_clicked();
    void on_actClear_triggered();


private:
    Ui::MainWindow *ui;

};
#endif // MAINWINDOW_H

ESP8266AT指令:

玩转ESP8266-01——AT指令集_esp8266 at指令集-CSDN博客 

 MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->toolBox->setEnabled(false);
    ui->tabWidget->setEnabled(false);

    /*
     显示串口列表,QSerialPortInfo是Qt提供的一个类,用于获取系统上可用的串口信息。在你提供的代码中,
     portInfo是一个QSerialPortInfo类型的变量,用于迭代遍历可用的串口信息。
     QSerialPortInfo::availablePorts()是QSerialPortInfo类的一个静态函数,它返回一个包含系统上所有可用串口信息的列表。
    */
    foreach (QSerialPortInfo portInfo, QSerialPortInfo::availablePorts()) {
        //portInfo.portName()获取串口的名称,portInfo.description()获取串口的描述。
        ui->comboCom_Port->addItem(portInfo.portName()+":"+portInfo.description());
    }
    /*ui->comboCom_Port->count()返回组合框中的项数,表示可用串口的数量*/
    ui->comboCom_Port->setEnabled(ui->comboCom_Port->count()>0);
    /*QIODevice是Qt中用于输入/输出设备的基类,包括串口设备。readyRead是QIODevice类的一个信号,
     * 表示设备已准备好读取数据。*/
    connect(&comPort,&QIODevice::readyRead,this,&MainWindow::do_com_readyRead);

    //添加标准比特率
    ui->comboCom_Buad->clear();
    /*QSerialPortInfo::standardBaudRates() 是 QSerialPortInfo 类的静态函数,
     * 用于获取标准的串口波特率列表。*/
    foreach (qint32 baud, QSerialPortInfo::standardBaudRates()) {
        /*addItem() 函数,可以向组合框添加一个新的项。QString::number(baud) 是将 baud 转换为一个字符串*/
        ui->comboCom_Buad->addItem(QString::number(baud));
    }
    ui->comboCom_Buad->setCurrentText("115200");

    //给frame_CmdA和frame_CmdB里面的标签的clicked()函数加槽函数
    /*这行代码是用于查找名为 frame_CmdA 的父级窗口中所有类型为 TMyLabel* 的子控件,
     * 并将它们存储在 QList<TMyLabel*> 类型的变量 labList 中。*/
    QList<TMyLabel*> labList=ui->frame_CmdA->findChildren<TMyLabel*>();
    foreach (TMyLabel *lab, labList) {
        connect(lab,SIGNAL(clicked()),this,SLOT(do_label_clicked()));
    }

    /*QApplication::setOrganizationName("WWW-Qt") 设置应用程序的组织名称为
     * "WWW-Qt"。组织名称通常用于标识应用程序的开发者或提供者。
    QApplication::setApplicationName("ESP8266") 设置应用程序的名称为
    "ESP8266"。应用程序名称是应用程序在界面和其他上下文中显示的名称。*/
    QApplication::setOrganizationName("WWW-Qt");
    QApplication::setApplicationName("ESP8266");

    /*从注册表中载入数据*/
    loadFromReg();
}

MainWindow::~MainWindow()
{
    delete ui;
}
//UART发送 char* 字符串
void MainWindow::uartSend(QString cmd)
{
    ui->textCOM->appendPlainText(cmd);
    /*const char *bts = cmd.toLocal8Bit(): 这行代码将cmd字符串转换为本地8位字符编码(char数组)
     * 并将其赋值给bts变量。这通常是为了将字符串转换为适合进行串口通信的格式。*/
    const char *stdCmd=cmd.toLocal8Bit().data();

    /*comPort.write(bts): 这行代码使用comPort对象执行串口写入操作,
     * 将bts中的数据发送到串口。它将bts中的字节发送到已打开的串口。*/
    comPort.write(stdCmd);
}

void MainWindow::delayMs(int ms)
{
    QElapsedTimer timer;
    timer.start();
    /*timer.elapsed() 是一个函数调用,用于获取自计时器启动以来经过的时间,单位为毫秒。*/
    while(timer.elapsed()<ms)
        /*QApplication::processEvents() 是一个函数调用,用于处理当前的事件队列。*/
        QApplication::processEvents();
}

void MainWindow::loadFromReg()
{
    /*QSettings 类用于读取和写入应用程序的设置值。*/
    QSettings setting;/*在大多数操作系统上,QSettings 默认将设置数据存储在特定的配置文件中。*/
    /*setting.value("saved", false) 用于检索名为 "saved" 的设置值。如果之前已经保存了 "saved" 的值,
     * 那么将返回该保存的值;如果没有保存的值,则返回默认值 false。*/
    bool saved=setting.value("saved",false).toBool();
    if(!saved){
        return;
    }
    QList<QLineEdit*> editList=ui->frame_CmdA->findChildren<QLineEdit*>();
    foreach(QLineEdit *edit,editList){
        //通过 edit->objectName() 获取当前 QLineEdit 控件的对象名称
        QString editName=edit->objectName();
        //通过 setting.value(editName).toString() 从 setting 中读取与当前
        //QLineEdit 对象名称对应的设置值,并将其转换为字符串类型。
        edit->setText(setting.value(editName).toString());
    }
    //查找fram_CmdB中的QLineEdit对象,载入注册表里的数据
    editList = ui->frame_CmdB->findChildren<QLineEdit*>();
    foreach (QLineEdit *edit, editList) {
        QString editName=edit->objectName();
        edit->setText(setting.value(editName).toString());
    }
    ui->comboWiFi_UartBuad->setCurrentText(setting.value("Uart_Rate").toString());
    ui->editAP_Name->setText(setting.value("AP_Name").toString());
    ui->editAP_PWD->setText(setting.value("AP_PWD").toString());
    ui->editServer_IP->setText(setting.value("TCP_IP").toString());
    ui->spinServer_Port->setValue(setting.value("TCP_Port").toInt());
}

void MainWindow::saveToReg()
{
    QSettings  setting;
    /*setting.setValue("saved", true); 这行代码将键名为 "saved" 的设置项的值设置为 true。*/
    setting.setValue("saved",true);

    QList<QLineEdit*> editList = ui->frame_CmdA->findChildren<QLineEdit*>();
    foreach(QLineEdit *edit, editList)
    {
        QString editName= edit->objectName();
        setting.setValue(editName,edit->text());
    }

    editList = ui->frame_CmdB->findChildren<QLineEdit*>();
    foreach(QLineEdit *edit, editList)
    {
        QString editName= edit->objectName();

        /*setting.setValue(editName, edit->text()): 这行代码使用QSettings类的setValue()
         * 函数将当前QLineEdit对象的文本内容作为值,以editName作为键存储在设置(settings)中。*/
        setting.setValue(editName,edit->text());
    }

    setting.setValue("Uart_Rate",ui->comboWiFi_UartBuad->currentText());
    setting.setValue("AP_Name",ui->editAP_Name->text());
    setting.setValue("AP_PWD",ui->editAP_PWD->text());
    setting.setValue("TCP_IP",ui->editServer_IP->text());
    setting.setValue("TCP_Port",ui->spinServer_Port->value());
}

void MainWindow::closeEvent(QCloseEvent *event)
{/*if (comPort.isOpen()) 这一行代码判断串口对象 comPort 是否已经打开。如果串口已经打开,
    那么接下来的代码块 comPort.close(); 将会被执行,关闭串口。*/
    if (comPort.isOpen()) {
        comPort.close();
    }
    saveToReg();
    /*如果一个事件处理程序调用了 event->accept(),
     * 则表示该事件已经被处理并且不需要传播给其他对象进行进一步处理。*/
    event->accept();
}
//接收数据
void MainWindow::do_com_readyRead()
{/*QByteArray all = comPort.readAll(); 这行代码从串口对象
   comPort 中读取所有可用的数据,并将其存储在 QByteArray 类型的变量 all 中。*/
    QByteArray all=comPort.readAll();
    QString str(all);
    ui->textCOM->appendPlainText(str);
}

void MainWindow::do_label_clicked()
{
    //获取信号发送者
    TMyLabel *lab=static_cast<TMyLabel*>(sender());
    //获取伙伴组件
    QLineEdit *edit=static_cast<QLineEdit *>(lab->buddy());
    QString cmd=edit->text().trimmed();
    if(ui->chkBox_NewLine2->isChecked()){
        cmd=cmd+"\r\n";
    }
    uartSend(cmd);
}

void MainWindow::on_actCom_Open_triggered(){
    if(comPort.isOpen()){
        QMessageBox::warning(this,"错误","打开串口时出现错误");
        return;
    }
    /*QSerialPortInfo::availablePorts() 函数用于获取当前系统中可用的串口列表,并将其存储在 comList 变量中。
     * QSerialPortInfo 类提供了有关串口的信息,包括串口名称、描述、制造商等。*/
    QList<QSerialPortInfo> comList=QSerialPortInfo::availablePorts();
    /*ui->comboCom_Port->currentIndex() 获取了名为 comboCom_Port 的组合框当前选中项的索引。
     * 这个索引将用于从 comList 中选择对应的串口信息。
     comList.at(ui->comboCom_Port->currentIndex()) 使用索引从 comList
     中获取对应位置的串口信息,并将其存储在 portInfo 变量中。*/
    QSerialPortInfo portInfo=comList.at(ui->comboCom_Port->currentIndex());
    /*comPort.setPort(portInfo) 将获取到的串口信息配置到 comPort 对象上。*/
    comPort.setPort(portInfo);

    //设置串口通信参数
    QString str=ui->comboCom_Buad->currentText();
    //设置波特率
    comPort.setBaudRate(str.toInt());
    int value=ui->comboCom_DataBit->currentText().toInt();

    //设置数据位
    //QSerialPort::DataBits(value) 将 value 转换为 QSerialPort::DataBits 类型。
    comPort.setDataBits(QSerialPort::DataBits(value));

    //停止位
    /*currentIndex():这是调用comboCom_StopBit对象的成员函数,用于获取当前选中项的索引。

    1+ui->comboCom_StopBit->currentIndex():这个表达式将当前索引的值加1,
    得到最终的计算结果,然后将结果赋给value变量。*/
    value=1+ui->comboCom_StopBit->currentIndex();
    comPort.setStopBits(QSerialPort::StopBits(value));
    //校验位
    if(ui->comboCom_Parity->currentIndex()==0){
        value=0;
    }else {
        value=1+ui->comboCom_Parity->currentIndex();
    }
    comPort.setParity(QSerialPort::Parity(value));

    if(comPort.open(QIODeviceBase::ReadWrite)){
        ui->frame_Port->setEnabled(false);
        ui->actCom_Open->setEnabled(false);
        ui->actCom_Close->setEnabled(true);
        //ESP8266操作面板
        ui->toolBox->setEnabled(true);
        ui->tabWidget->setEnabled(true);
        QMessageBox::information(this,"提示信息","串口已经被成功打开");
    }

}

//关闭串口
void MainWindow::on_actCom_Close_triggered()
{
    if(comPort.isOpen()){
        comPort.close();
        ui->frame_Port->setEnabled(true);
        ui->actCom_Open->setEnabled(true);
        ui->actCom_Close->setEnabled(false);
        ui->toolBox->setEnabled(false);
        ui->tabWidget->setEnabled(false);
    }
}

//查询WiFi模块的UART参数
void MainWindow::on_btnWF_UART_Qry_clicked()
{
    QString cmd="AT+UART?\r\n";
    uartSend(cmd);
}
//使WiFi模块重启,模块重启后可能会进入透传模式
void MainWindow::on_btnWF_Reset_clicked()
{
    QString cmd="AT+RST\r\n";
    uartSend(cmd);
}
//WiFi模块测试指令,返回OK就是测试成功
void MainWindow::on_btnWF_Test_clicked()
{
    QString cmd="AT\r\n";
    uartSend(cmd);
}
//设置UART参数
void MainWindow::on_btnWF_UART_Set_clicked()
{
    QString rate=ui->comboWiFi_UartBuad->currentText().trimmed();
    QString cmd="AT+UART="+rate+",8,1,0,0\r\n";
    uartSend(cmd);
}
//退出透传模式
/*在串口通信中,透传模式通常用于将数据直接从一个串口端口传递到另一个串口端口,而不对数据进行任何修改或解析。
 * 这意味着数据以原始的字节流形式在两个端点之间传递,不做任何额外的处理。*/
void MainWindow::on_btnTrans_Exit_clicked()
{
    QString cmd="+++";
    uartSend(cmd);

    delayMs(2000);
    //  QApplication::processEvents();
    //	comPort.waitForReadyRead(3000);	//等待3000ms,直到有数据接收到
    //	QApplication::processEvents();

    cmd="AT+CIPMODE=0\r\n";
    uartSend(cmd);
}
//进入透传模式
void MainWindow::on_btnTrans_Enter_clicked()
{
    QString cmd="AT+CIPMODE=1\r\n";
    uartSend(cmd);

    //        QApplication::processEvents();
    //        comPort.waitForReadyRead(2000);	//等待2000ms,直到有数据接收到
    //        QApplication::processEvents();    //这种处理方式错误

    delayMs(2000);
    cmd="AT+CIPSEND\r\n";
    uartSend(cmd);
}
//查询模块的MAC和IP地址
void MainWindow::on_btnTCP_GetMac_clicked()
{
    QString cmd="AT+CIFSR\r\n";
    uartSend(cmd);
}
//查询路由器参数
void MainWindow::on_btnWF_GetAP_clicked()
{
    QString cmd="AT+CWJAP?\r\n";
    uartSend(cmd);
}
//查询模块当前连接状态,
void MainWindow::on_btnTCP_Query_clicked()
{
    QString cmd="AT+CIPSTATUS\r\n";
    uartSend(cmd);
}
//将WiFi模块设置为STA
void MainWindow::on_btnWF_SetAsSTA_clicked()
{
    QString cmd="AT+CWMODE=1\r\n";
    uartSend(cmd);
}
// 设置路由器参数
// AT+CWJAP="LINK_WHY","pai06why"
void MainWindow::on_btnWF_SetAP_clicked()
{
    QString APname=ui->editAP_Name->text().trimmed();
    QString APpswd=ui->editAP_PWD->text().trimmed();
    QString cmd="AT+CWJAP=\""+ APname+"\","+"\""+APpswd+"\"\r\n";
    uartSend(cmd);
}
//设置TCP服务器参数
//	AT+CIPSTART="TCP","192.168.146.132",8080
void MainWindow::on_btnTCP_SetServer_clicked()
{
    QString ServerIP=ui->editServer_IP->text().trimmed();
    int serverPort=ui->spinServer_Port->value();
    /*strPort.setNum(serverPort); 这一行代码调用了 setNum() 函数,
     * 将整数变量 serverPort 的值转换为字符串,并将结果存储在 strPort 中。*/
    QString strPort;
    strPort.setNum(serverPort);

    QString cmd="AT+CIPSTART=\"TCP\",\""+ ServerIP+"\","+strPort+"\r\n";
    uartSend(cmd);
}
//恢复出厂设置,模块会重启
void MainWindow::on_pushButton_4_clicked()
{
    if (QMessageBox::question(this,"请确认","确定要恢复出厂设置吗?\r\n这将删除所有自定义设置",
                              QMessageBox::Yes|QMessageBox::Cancel) ==QMessageBox::Yes)
    {
        QString cmd="AT+RESTORE\r\n";
        uartSend(cmd);
    }
}

void MainWindow::on_btnTrans_AutoOnReset_clicked()
{
    QString ServerIP=ui->editServer_IP->text().trimmed();
    int serverPort=ui->spinServer_Port->value();
    QString strPort;
    strPort.setNum(serverPort);

    QString cmd="AT+SAVETRANSLINK=1,\""+ ServerIP+"\","+strPort+",\"TCP\""+"\r\n";
    uartSend(cmd);
}

void MainWindow::on_btnNormSend_clicked()
{
    QString cmd=ui->plainText_Norm->toPlainText();
    if (ui->chkBox_NewLine1->isChecked()){
        cmd = cmd+"\r\n";
    }

    uartSend(cmd);
}

void MainWindow::on_btnTCP_AutoConn_clicked()
{
    QString cmd="AT+CWAUTOCONN=1\r\n";
    uartSend(cmd);
}

void MainWindow::on_actClear_triggered()
{
    ui->textCOM->clear();
}

 

 

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值