文章目录

  • 硬件
  • 软件
  • 服务器
  • 代码编写
    • esp8266
  • EMQ服务器的使用
    • STM32发布、服务器订阅
    • STM32订阅、服务器发布
  • MQTT客户端的使用
    • 移植

硬件

STM32F103C8T6

ESP-01S

软件

  • SYS->Debug->Serial Wire
  • RCC->HSE->Crystal/Ceramic Resonator
  • PC13->GPIO_Out
  • USART1->Mode->Asynchronous ,参数默认
  • USART2>Mode->Asynchronous ,参数默认
  • NVIC->USART2 global interrupt->Enabled

串口1与上位机tongxin

串口2与服务器通信

服务器

本次使用的MQTT服务器,有钱的朋友们也可以自行去阿里云购买一个自己的云服务器。

EMQX。EMQX Cloud 是 EMQ 公司推出的一款面向物联网领域的 MQTT 消息中间件产品。作为全球首个全托管的 MQTT 5.0 公有云服务,EMQX Cloud 提供了一站式运维代管、独有隔离环境的 MQTT 消息服务。在万物互联的时代,EMQX Cloud 可以帮助您快速构建面向物联网领域的行业应用,轻松实现物联网数据的采集、传输、计算和持久化。

此网站提供了一个免费在线MQTT 5服务器

Broker broker-cn.emqx.io
TCP端口 1883
Websocket端口 8083
TCP/TLS端口 8883
Websocket/TLS端口 8084
CA证书文件 broker.emqx.io-ca.crt

代码编写

程序中主要的文件有

  • esp8266.c esp8266.h
  • MqttKit.c MqttKit.h
  • onenet.c onenet.h
  • cJSON.c cJSON.h

将上述文件分别添加到Inc和Src中,可能会遇到以下情况

这时只要重新加载一下CMakeLists.txt

esp8266

模块使用的是安心可得ESP-01S

ESP-01S 是由安信可科技开发的 Wi-Fi 模块,该模块核心处理器ESP8266 在较小尺寸封装中集成了业界领先的 Tensilica L106 超低功耗 32 位微型MCU,带有16位精简模式,主频支持 80 MHz 和 160 MHz,支持 RTOS,集成Wi-Fi MAC/ BB/RF/PA/LNA。ESP-01S Wi-Fi 模块支持标准的 IEEE802.11 b/g/n 协议,完整的TCP/IP 协议栈。用户可以使用该模块为现有的设备添加联网功能,也可以构建独立的网络控制器。

esp8266.h

#ifndef __esp_H
#define __esp_H#include "main.h"#define REV_OK    0  //接收完成标志
#define REV_WAIT   1  //接收未完成标志typedef _Bool        uint1;
typedef unsigned char   uint8;
typedef char         int8;
typedef unsigned short  uint16;
typedef short        int16;
typedef unsigned int    uint32;
typedef int             int32;
typedef unsigned int   size_t;void Usart_SendString(UART_HandleTypeDef *USARTx, unsigned char *str, unsigned short len);void UsartPrintf(UART_HandleTypeDef *huart, char *fmt,...);void ESP8266_Init(void);//esp8266初始化void ESP8266_Clear(void); //清空缓存void ESP8266_SendData(unsigned char *data, unsigned short len);//发送数据unsigned char *ESP8266_GetIPD(unsigned short timeOut);//获取平台返回的数据#endif

下面介绍以下几个重要功能函数

/*
************************************************************
*  函数名称:  Usart_SendString
*
*  函数功能:  串口数据发送
*
*  入口参数:  USARTx:串口组
*           str:要发送的数据
*           len:数据长度
*
*  返回参数:  无
*
*  说明:
************************************************************
*/
void Usart_SendString(UART_HandleTypeDef *USARTx, unsigned char *str, unsigned short len)
{uint16_t j;for(j=0;j<len;j++)//循环发送数据{while((USART2->SR&0X40)==0);//循环发送,直到发送完毕USART2->DR=*str++;}
}
/*
************************************************************
*  函数名称:  UsartPrintf
*
*  函数功能:  格式化打印
*
*  入口参数:  USARTx:串口组
*           fmt:不定长参
*
*  返回参数:  无
*
*  说明:
************************************************************
*/
void UsartPrintf(UART_HandleTypeDef *huart, char *fmt,...)
{int printf_TXBUFFERSIZE=1026;char buffer[printf_TXBUFFERSIZE];int i=0;va_list arg_ptr;va_start(arg_ptr,fmt);vsnprintf(buffer,printf_TXBUFFERSIZE+1,fmt,arg_ptr);while((i<printf_TXBUFFERSIZE)&&buffer[i]){HAL_UART_Transmit(huart,(uint8_t *)&buffer[i++],1,0xFFFF);}va_end(arg_ptr);}

上述两个函数在usart.c中都没有定义,需要自己定义串口数据发送和格式化打印函数。

esp8266初始化函数

void ESP8266_Init(void)
{__HAL_UART_ENABLE_IT(&huart2,UART_IT_RXNE);//使能串口接收中断ESP8266_Clear();UsartPrintf(&huart1, "> 0. AT - 测试MCU-8266通讯\r\n");while(ESP8266_SendCmd("AT\r\n", "OK"))HAL_Delay(500);UsartPrintf(&huart1, "> 1. AT+RST - 软复位8266\r\n");ESP8266_SendCmd("AT+RST\r\n", "");HAL_Delay(500);ESP8266_SendCmd("AT+CIPCLOSE\r\n", "");HAL_Delay(500);UsartPrintf(&huart1, "> 2. AT+CWMODE=1,1 - 设置8266工作模式为STA\r\n");while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))HAL_Delay(500);UsartPrintf(&huart1, "> 3. AT+CWDHCP=1,1 - 使能STA模式下DHCP\r\n");while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))HAL_Delay(500);UsartPrintf(&huart1, "> 4. AT+CWJAP - 连接WIFI\r\n");while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))HAL_Delay(500);UsartPrintf(&huart1, "> 5. AT+CIPSTART - 连接服务器\r\n");while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))HAL_Delay(500);ESP8266_INIT_OK = 1;UsartPrintf(&huart1, "> 6. ESP8266 Init OK - ESP8266初始化成功\r\n");
}

通过串口1实时打印esp8266的状态,串口2通过esp8266发送指令连接wifi、连接服务器等

ESP8266_WIFI_INFOESP8266_ONENET_INFO两个宏定义为

#define WIFI_SSID                  "******"                      // WIFI的名称 必须用2.4G的wifi不能用5G的,且不能用中文、空格
#define WIFI_PSWD                 "******"             // WIFI密码#define SERVER_HOST                   "broker.emqx.io"         // MQTT服务器域名或IP
#define SERVER_PORT                   "1883"                      // MQTT服务器端口(一般为1883不用改)#define ESP8266_WIFI_INFO        "AT+CWJAP=\"" WIFI_SSID "\",\"" WIFI_PSWD "\"\r\n"#define ESP8266_ONENET_INFO       "AT+CIPSTART=\"TCP\",\"" SERVER_HOST "\"," SERVER_PORT "\r\n"

在移植过程中只需修改上述宏即可

main.c

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "esp8266.h"
#include "onenet.h"
/* USER CODE END Includes *//* USER CODE BEGIN PV */
const char *devSubTopic[] = {"/mysmarthome/sub"};
const char devPubTopic[] = "/mysmarthome/pub";
uint8_t ESP8266_INIT_OK = 0;//esp8266初始化完成标志
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 */unsigned short timeCount = 0;  //发送间隔变量unsigned char *dataPtr = NULL;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_USART2_UART_Init();/* USER CODE BEGIN 2 */UsartPrintf(&huart1, "Hardware init OK\r\n");ESP8266_Init();                //初始化ESP8266while(OneNet_DevLink())HAL_Delay(500);//接入OneNETOneNet_Subscribe(devSubTopic, 1);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(++timeCount >= 200)                           //发送间隔5s{UsartPrintf(&huart1, "OneNet_Publish\r\n");OneNet_Publish(devPubTopic, "MQTT Publish Test");timeCount = 0;ESP8266_Clear();}//数据解析dataPtr = ESP8266_GetIPD(3);if(dataPtr != NULL)OneNet_RevPro(dataPtr);HAL_Delay(10);}/* USER CODE END 3 */
}

主函数中,以下这几处都跟stm32与服务器实现发布与订阅有重要作用

OneNet_Subscribe(devSubTopic, 1);//订阅的话题和话题数量
OneNet_Publish(devPubTopic, "MQTT Publish Test");//发布的话题和话题内容
dataPtr = ESP8266_GetIPD(3);//获取平台返回的数据
OneNet_RevPro(dataPtr);//如果数据不为空,则对数据处理

下面是发布和订阅的话题名称,可自行修改

/* USER CODE BEGIN PV */
const char *devSubTopic[] = {"/mysmarthome/sub"};
const char devPubTopic[] = "/mysmarthome/pub";
/* USER CODE END PV */

对发布内容来说,修改msg的值即可确定stm32发布给服务器的内容

void OneNet_Publish(const char *topic, const char *msg)

而stm32订阅服务器的数据(即服务器发布给stm32的数据)需要在OneNet_RevPro函数中对数据进行json处理。

void OneNet_RevPro(unsigned char *cmd)
{MQTT_PACKET_STRUCTURE mqttPacket = {NULL, 0, 0, 0};                         //协议包char *req_payload = NULL;char *cmdid_topic = NULL;unsigned short topic_len = 0;unsigned short req_len = 0;unsigned char type = 0;unsigned char qos = 0;static unsigned short pkt_id = 0;short result = 0;char *dataPtr = NULL;char numBuf[10];int num = 0;cJSON *json , *json_value;type = MQTT_UnPacketRecv(cmd);switch(type){case MQTT_PKT_CMD:                                           //命令下发result = MQTT_UnPacketCmd(cmd, &cmdid_topic, &req_payload, &req_len);  //解出topic和消息体if(result == 0){UsartPrintf(&huart1, "cmdid: %s, req: %s, req_len: %d\r\n", cmdid_topic, req_payload, req_len);MQTT_DeleteBuffer(&mqttPacket);                            //删包}break;case MQTT_PKT_PUBLISH:                                        //接收的Publish消息result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id);if(result == 0){UsartPrintf(&huart1, "topic: %s, topic_len: %d, payload: %s, payload_len: %d\r\n",cmdid_topic, topic_len, req_payload, req_len);// 对数据包req_payload进行JSON格式解析json = cJSON_Parse(req_payload);//对发布的数据进行json解析if (!json)UsartPrintf(&huart1, "Error before: [%s]\n", cJSON_GetErrorPtr());else {json_value = cJSON_GetObjectItem(json, "LED");if (json_value->valueint)HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);//开灯elseHAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);//关灯}cJSON_Delete(json);}break;case MQTT_PKT_PUBACK:                                         //发送Publish消息,平台回复的Ackif(MQTT_UnPacketPublishAck(cmd) == 0)UsartPrintf(&huart1, "Tips:    MQTT Publish Send OK\r\n");break;default:result = -1;break;}ESP8266_Clear();                           //清空缓存if(result == -1)return;if(strstr((char *)req_payload, "OPEN"))       //搜索"OPEN"{UsartPrintf(&huart1, "Blue_Led_ON\r\n");}else if(strstr((char *)req_payload, "CLOED"))  //搜索"CLOED"{UsartPrintf(&huart1, "Blue_Led_OFF\r\n");}if(type == MQTT_PKT_CMD || type == MQTT_PKT_PUBLISH){MQTT_FreeBuffer(cmdid_topic);MQTT_FreeBuffer(req_payload);}}

移植过程中只需要修改下面这部分内容即可

 case MQTT_PKT_PUBLISH:                                        //接收的Publish消息       result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id);if(result == 0){UsartPrintf(&huart1, "topic: %s, topic_len: %d, payload: %s, payload_len: %d\r\n",cmdid_topic, topic_len, req_payload, req_len);// 对数据包req_payload进行JSON格式解析json = cJSON_Parse(req_payload);//对发布的数据进行json解析if (!json)UsartPrintf(&huart1, "Error before: [%s]\n", cJSON_GetErrorPtr());else {json_value = cJSON_GetObjectItem(json, "LED");if (json_value->valueint)//json_value > 0且为整形HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);//开灯elseHAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);//关灯}cJSON_Delete(json);}break;

发布数据时要以json格式进行发送eg:{"msg": "hello"}

上述中当我们发布{"LED":1},LED等就为高电平,{"LED":0},LED等就为低电平

烧录程序后,连接串口,打开自己的手机热点(必须用2.4G的wifi不能用5G的),然后出现以下情况及表示连接服务器成功。

EMQ服务器的使用

首先登录官网EMQX,找到学习下的MQTT WebSocket客户端

进去之后,点击适用

创建新的连接,自定义Name,Host和Port修改成自己的服务器名即可,然后Connect

STM32发布、服务器订阅

New Subscription->订阅stm32的发布话题/mysmarthome/pub

此时就会看到stm32向服务器发来的消息MQTT Publish Test,实现

STM32订阅、服务器发布

将Payload选为JSON格式发布,topic为/mysmarthome/sub,发布内容为{"LED":1}{"LED":0},实现控制stm32的LED亮灭。

注意!!!,在新建发布与订阅话题中,有一项为QoS,此选项要与STM32中一致

分别在onenet.c中的OneNet_SubscribeOneNet_Publish函数中

MQTT客户端的使用

上面中使用是在线发布与订阅,下面使用MQTT软件实现发布订阅

下载地址MQTT.fx

打开之后点击小齿轮新建连接

然后Apply,Connect之后就可以发布和订阅话题了

订阅话题

发布话题

移植

下面总结下移植时需要修改的参数

参数 说明
WIFI_SSID WIFI的名称 必须用2.4G的wifi不能用5G的,且不能用中文、空格
WIFI_PSWD WIFI密码
SERVER_HOST MQTT服务器域名或IP
SERVER_PORT MQTT服务器端口(一般为1883不用改)
*devSubTopic[] 订阅话题
devPubTopic[] 发布话题
OneNet_Publish(const char *topic, const char *msg) 发布内容
cJSON_GetObjectItem(json, “LED”); 对订阅的命令做出判断

资源下载

STM32-esp8266-MQTT服务器通信相关推荐

  1. STM32+ESP8266+MQTT微信小程序SoftAP一键配网接入腾讯物联网平台

    STM32+ESP8266+MQTT微信小程序SoftAP一键配网接入腾讯物联网平台   Wi-Fi 配网,指由外部向 Wi-Fi 设备提供 SSID 和密码(PSW),让 Wi-Fi 设备可以连接指 ...

  2. STM32+ESP8266+MQTT协议连接阿里云物联网平台

    一.环境介绍 单片机采用:STM32F103C8T6 上网方式:采用ESP8266,也可以使用其他设备代替,只要支持TCP协议即可.比如:GSM模块.有线网卡等. 开发软件:keil5 硬件连接功能: ...

  3. STM32+ESP8266+MQTT协议连接腾讯物联网开发平台

    一.环境介绍 单片机采用:STM32F103C8T6 上网方式:采用ESP8266,也可以使用其他设备代替,只要支持TCP协议即可.比如:GSM模块.有线网卡等. 开发软件:keil5 物联网平台: ...

  4. STM32+ESP8266+MQTT连接阿里云服务器(一、烧写MQTT固件)

    用STM32连接阿里云服务器首先ESP8266得支持MQTT的AT指令,所以!!!在连接阿里云服务器时,得先对ESP8266进行固件替换. 工具 硬件:ATK-ESP8266.USB转串口 软件:fl ...

  5. STM32+ESP8266+MQTT连接阿里云服务器(四、STM32连接阿里云平台)

    材料: STM32F103.ESP8266.串口 第三章介绍了利用串口调试助手+AT指令连接阿里云平台的,现在用代码去实现其功能,利用STM32的串口2跟WIFI模块进行数据通信即可.这里我实现的功能 ...

  6. Finger.03 - ESP8266与MQTT服务器通信

    1.已调通,文章待整理 2.相关资料 每个模块的使用:https://nodemcu.readthedocs.io/en/release/ Lua语言相关:https://www.runoob.com ...

  7. 【最简单】STM32+ESP8266+MQTT+EMQX完成数据上传和点灯环节

    首先要吐槽一点,那就是网络上的这方面资料杂七杂八,而且很多都是一模一样的: 然后我作为一个学生,没有多大的本事,就是想实现最基本的功能,然后在此基础上慢慢拓展.所以那些十分庞大的工程或者一些IoT物联 ...

  8. STM32+ESP8266连接服务器失败,不断发送OneNet_DevLink

    修改onenet.c文件上方的PROID,AUTH_INFO,DEVID即可, 不要使用默认的 #define PROID "77247"#define AUTH_INFO &qu ...

  9. 快速搭建MQTT服务器(MQTTnet和Apache Apollo)

    前言 MQTT协议是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分,http://mqtt.org/. MQTT is a machine-to-machine (M2M)/" ...

  10. 【STM32 x ESP8266】连接 MQTT 服务器(报文,附部分源码解析)

    MQTT 协议作为物联网非常重要的传输协议,如何使用它十分重要,如果有不理解的同学可以点击这里学习,这里只是简单介绍一下.同时这里附上MQTT 3.1.1协议中文版 pdf 的链接,对协议底层感兴趣的 ...

最新文章

  1. html post 图片,如何发送图片作为多部分POST请求的一部分 - Java HtmlUnit
  2. AndroidのUI设计研究(一)——自定义ProgressBar
  3. 我的第一个Android程序
  4. shell 登录mysql 然后quit_使用工具Xshell实现在linux上登录mysql和退出mysql的相关操作讲解...
  5. POJ-排序-归并排序与逆序对
  6. 【Trie】最长异或路径(ybtoj Trie-3/luogu 4551)
  7. 处理对象(toString()方法详解和==与equals方法的区别)
  8. java连接mysql通用方法_jdbc操作数据库通用方法
  9. 使用CSE轻松实现接口访问控制
  10. SQL数据导出至Excel
  11. pdfbox创建pdf_使用PDFBox处理PDF文档(新建PDF文件、修改PDF文件、PDF中插入图片、将PDF文件转换为图片)...
  12. vue 开发app处理手机返回键问题
  13. Java - ip2region - 使用篇
  14. 手把手教你用frp内网穿透
  15. 《从工业化到城市化》
  16. mysql-5.5.20-winx64_mysql-5.7.20-winx64命令安装
  17. Python+医学院校二手书管理 毕业设计-附源码201704
  18. 概率论:魏布斯分布Weibull cumulative distribution function
  19. 矛盾集合体——static的相关用法介绍
  20. VLSI MP3 音频 编解码芯片

热门文章

  1. labview--VIPM(VI package manager)打开后闪退
  2. tflearn的VocabularyProcessor用法:建立中文词汇表和把文本转为词ID序列
  3. Spring Admin 入门
  4. 【信奥题库 NOIP 2020 在线模拟赛 T1】有趣的函数
  5. 算法笔记 之 埃拉托色尼筛选法(筛选质数)
  6. freeswitch-PSTN
  7. 一次大文件上传失败的排查
  8. manager objects is not callable(管理器对象不可调用)
  9. Linux环境中第一行dpa,nvdimm
  10. 锐捷交换机的环路检测