ESP8266中原本的固件是没有MQTT相关的AT指令的,需要通过烧录固件使其支持对应的AT指令。
参考链接:https://blog.csdn.net/qq_43819071/article/details/132111194
烧录之前确保ESP8266的各个引脚必须连接正确,I0必须接地。
3.3V/5V ------ 3.3V/5V
RX ------ TX
TX ------ RX
GND ------ GND
I0 ------ GND
在烧录成功之后,拔掉I0接口,使其进去工作模式,通过串口工具测试MQTT的AT指令能否正确连接。
先将STM32 与ESP8266连接的串口初始化。我这里采用的是UART4,连接到的MQTT服务器是巴法云,官网:https://cloud.bemfa.com/,注册后即可正常连接 代码如下:
void Configure_ESP8266_MQTT(void) { rst_wifi(); delay_ms(500); ESP8266_Clear(); //1 AT while(ESP8266_SendCmd("AT\r\n\r", "OK", 200)) { printf("AT Failed\r\n"); } //2 将Wi-Fi模块设置为Station(STA)模式 while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK", 50)) { printf("STA Failed\r\n"); } //3 连接WIFI的用户名和密码 while(ESP8266_SendCmd("AT+CWJAP=\"ChinaNet-NrgD\",\"rnq265xq\"\r\n", "OK", 500)) { printf("WIFI Failed\r\n"); } //4 设置MQTT相关属性 while(ESP8266_SendCmd("AT+MQTTUSERCFG=0,1,\"clientid\",\"username\",\"password\",0,0,\"\"\r\n", "OK", 500)) { printf("MQTT Failed\r\n"); } //5 连接MQTT的ip while(ESP8266_SendCmd("AT+MQTTCONN=0,\"bemfa.com\",9501,1\r\n", "OK", 500)) { printf("MQTT Failed\r\n"); } //6 订阅主题 while(ESP8266_SendCmd("AT+MQTTSUB=0,\"LED2002\",0\r\n", "OK", 50)) { printf("Sub Failed\r\n"); } //6 订阅主题 while(ESP8266_SendCmd("AT+MQTTSUB=0,\"LED1002\",0\r\n", "OK", 50)) { printf("Sub Failed\r\n"); } //6 订阅主题 while(ESP8266_SendCmd("AT+MQTTSUB=0,\"RGB1002\",0\r\n", "OK", 50)) { printf("Sub Failed\r\n"); } }
在连接之前,必须先将ESP8266模块Reset ,即代码中的 rst_wifi()函数,才能保证能正常连接。
void rst_wifi(void) { GPIO_ResetBits(GPIOI, GPIO_Pin_10); delay_ms(1000); GPIO_SetBits(GPIOI, GPIO_Pin_10); }
其中ESP8266_SendCmd()函数采用的是正点原子ESP8266资料中的与之相关函数。
代码如下:
//========================================================== // 函数名称: ESP8266_AnalyzeMessagv // // 函数功能: 处理平台返回的数据 // //========================================================== void ESP8266_AnalyzeMessagv(void) { if(ESP8266_WaitRecive() == REV_OK) //如果接收完成 { if(strstr((char *)esp8266_buf, "+MQTTSUBRECV")) { ......//在这里写接收到的命令分析 } } }
参考链接:https://blog.csdn.net/LclLsh/article/details/126536614
需要注意的是,需要下载与自己QT版本相同的QtMqtt库,编译时使用release。在编译完成后,将对应的库放到对应的编译器下,MINGW和MSVC、32位和64位必须一一对应。
在mainwindow.h中插入需要的头文件
#include #include #include #include #include #include
MQTT链接部分代码:
在构造函数中添加以下代码
m_client = new QMqttClient(this); hostPort = 9501; hostName ="bemfa.com"; m_client->setHostname(hostName); m_client->setClientId("e917d4e4b461831638744a74f2337704"); m_client->setPort(hostPort); m_client->setKeepAlive(120); m_client->connectToHost(); connect(m_client,&QMqttClient::connected,this,&MainWindow::isConnected); connect(m_client, &QMqttClient::stateChanged, this, &MainWindow::updateLogStateChange); connect(m_client, &QMqttClient::disconnected, this, &MainWindow::brokerDisconnected); connect(m_client, &QMqttClient::pingResponseReceived, this, [this]() { const QString content = QDateTime::currentDateTime().toString() +QString(" ") + QLatin1String(" PingResponse") + QLatin1Char('\n'); qDebug() << content; });
其余函数代码如下:
void MainWindow::isConnected() { QString topic = "dht004"; if(m_client->state() == QMqttClient::Connected){ m_client->subscribe(QString(topic), 0); connect(m_client, SIGNAL(messageReceived(QByteArray,QMqttTopicName)), this, SLOT(topicMessageReceived(QByteArray,QMqttTopicName))); } } void MainWindow::brokerDisconnected() { qDebug()<<"Connect disconnected"; } void MainWindow::updateLogStateChange() { const QString content = QDateTime::currentDateTime().toString() + QLatin1String(": State Change") +QString(" ") + QString::number(m_client->state()) + QLatin1Char('\n'); qDebug() << content; } void MainWindow::topicMessageReceived(const QByteArray &message,const QMqttTopicName &topic) { if(topic.name() == "dht004") { int temperature = message.split('#').at(1).toInt(); int humidity = message.split('#').at(2).toInt(); ui->gaugeWeather->setOuterValue(humidity); //设置外环初始值为0 ui->gaugeWeather->setInnerValue(temperature); //设置内环初始值为0 } }
QT显示部分,使用了feiyangqingyun大佬设计的组件,相关链接:https://qtchina.blog.csdn.net/article/details/97565652。
STM32 端代码下载:https://download.csdn.net/download/qq_43579230/75256786