标题直接 Buff 点满…

阅读指引

如果你是 0 基础选手,建议先阅读以下内容掌握基本的 FreeRTOS 工程知识:

  1. C 语言基本语法
  2. STM32 工程创建,详看
  3. FreeRTOS 的移植,详看

本文主要分为三个部分,每个部分需要准备的工具如下:

  1. 阿里云物联网平台注册:需要阿里云账号。
  2. 模拟 MQTT 客户端发送与订阅消息:软件 MQTT.fx,阿里云提供的 MQTT_Password 工具。
  3. ESP8266 固件烧录:串口助手软件,需要材料 ESP8266、USB-TTL、杜邦线若干。
  4. 软件实现:Keil 软件、STM32CubeMX(使用 HAL)、STM32、DHT11、杜邦线若干、OLED(可选)、LED 灯、ST-Link
阅读前的提示
  1. 阿里云相关产品新用户只能免费试用 1 个月。比如物联网企业版实例新用户可以试用 1 个月,但也有公共实例永久免费使用。增值服务 IoT Studio 用于绘制可视化界面,可以试用 1 个月,但其实这也不是必须的,就是提供了一个可视化界面而已。
  2. MQTT 功能是通过固件烧录进ESP8266中的,不是 MQTT 协议在 FreeRTOS 上的移植。
  3. 如果只是单纯实现温湿度监控及点灯的话,FreeRTOS 其实不是必须的。

接线图与实物图展示

Visio 随便画的,感觉掌握不到诀窍,很难画。

image.png

下图有个多余连接的串口,读者可以忽略。

image.png

UML

如果 UML 图不规范请指出哈。我感觉 UML 图我永远画不对…

用例图:

阿里云物联网平台STM32监测温湿度数据控制LED灯读取监测数据获取温湿度数据发送温湿度数据至物联网平台接收LED控制信号设置LED灯用户«include»«include»«include»

用户通过阿里云物联网平台进行温湿度数据监测以及 LED 灯控制,此外,用户还可通过直接观察设备显示屏读取温湿度监测数据。对于通过阿里云物联网平台监测温湿度数据的用例,除了在远程平台实现可视化界面外,STM32 需实现将温湿度数据发送至远程平台的能力。无论是温湿度数据的本地展示或远程发送,都依赖于 STM32 中获取温湿度数据用例。该用例需要 STM32 与温湿度监测设备进行数据交互。远程平台中控制 LED 灯用例的实现不仅依赖于物联网平台提供的指令发送接口,也需要 STM32 实现信号的接收与 LED 灯设置的功能。

发送温湿度过程顺序图:

用户用户单片机单片机温湿度传感器温湿度传感器显示设备显示设备WIFI模块WIFI模块MQTT BrokerMQTT Broker请求查询温湿度数据温湿度数据发送温湿度数据展示温湿度数据发送温湿度数据发送温湿度数据在远程面板展示温湿度数据

单片机从监测设备获取温湿度数据并发送至阿里云物联网平台过程的顺序图如上图所示。单片机初始化完毕后,利用 FreeRTOS 任务函数定时向 DHT11 发送复位信号。DHT11 接收复位信号后将 40 Bit 的检测数据通过单总线协议传输至 STM32 处理。随后,STM32 利用该数据完成以下任务:

  1. 更新 OLED 显示屏,实现设备实时显示温湿度信息的功能。
  2. 将温湿度数据生成 AT 命令,通过串口发送至 ESP8266 模块中。

ESP8266 模块接收到 AT 指令后,将通过 MQTT 协议向阿里云物联网平台发布消息。阿里云物联网平台将根据该消息的主题与参数,更新可视化界面的网络应用,从而实现用户远程监控设备的功能。

接收 LED 灯指令顺序图:

用户用户MQTT BrokerMQTT BrokerWIFI模块WIFI模块单片机单片机LEDLED控制LED灯开关LED灯控制信号触发串口中断处理串口中断LED控制信息点亮LED灯点亮LED灯

用户通过网络应用的可视化界面控制设备 LED 灯的顺序图如上图所示。用户通过可视化界面操作 LED 灯状态为“0(关闭)”或“1(开启)”。MQTT Broker 向设备发送消息,该消息由连接至 STM32 单片机的 WIFI 模块接收。WIFI 模块将接收到的数据存放在串口缓冲区中,并设置标志位提醒 STM32 单片机进行接收。STM32 利用 FreeRTOS 任务调度,获取 WIFI 模块返回的信息并解析 LED 灯控制指令。最后根据指令控制 LED 灯电路,改变灯的状态。

阿里云物联网平台

此部分可参考官方文档:如何快速将设备接入物联网平台并控制其开关_物联网平台(IoT)-阿里云帮助中心 (aliyun.com)

添加产品物模型

首先你得拥有一个阿里云账号,然后开通物联网平台:

image.png

进入管理控制台:

image.png

创建一个实例(前提需实名认证):

image.png

标准实例可以免费开通试用 1 个月。

公共实例开通免费,但据说可能联网不佳,我试了一下感觉还行,没条件的可以直接使用公共实例。

进入实例详情:

image.png

创建一个产品:

image.png

创建设备:

image.png

下面添加一个物模型:

image.png

image.png

image.png

使用 IoT Studio 绘制界面

回到物联网平台,查看增值服务。如果没有 IoT Studio,可以在选购增值服务中购买。IoT Studio 可以试用 1 个月。

image.png

进入 IoT Studio,选择你的实例,新建 Web 应用:

image.png

image.png

绘制一个像样的页面:

image.png

仪表盘数据源配置:

image.png

image.png

折线图数据源配置:

image.png

按钮交互配置:

image.png

这时点击预览的话仪表盘会显示没有数据,可继续下一章节阅读。

MQTT.fx 模拟客户端发布与订阅消息

此部分可参考文档:使用MQTT协议模拟设备快速接入物联网平台_物联网平台(IoT)-阿里云帮助中心 (aliyun.com)

安装 MQTT_Password 工具包:如何计算MQTT签名参数_物联网平台(IoT)-阿里云帮助中心 (aliyun.com)

安装 MQTT.fx:MQTT.fx® Download (softblade.de)

回到阿里云物联网平台控制台>设备>查看,把三元素复制下来:

image.png

使用 MQTT_Password 计算签名:

image.png

除了此处的 Clientid 是需要填入的设备信息 Clientid,其他所有地方说的 Client ID 都是指 MQTT 连接的 Client ID 具体值就是计算结果的 mqttClientid

打开 MQTT.fx,配置:

image.png

image.png

Broker Address 为你的 ProductID+.iot-as-mqtt.cn-shanghai.aliyuncs.com

链接。然后尝试发布消息和订阅消息:

image.png

连接后阿里云物联网平台将显示在线:

image.png

尝试在 /sys/k10qu3ushCq/mqtt_stm32/thing/event/property/post 发布一个 json 数据:

1
{"params":{"temperature":42,"Humidity":22},"version":"1.0.0"}

image.png

结果在 IoT Studio 网页应用就会显示数据:

image.png

/sys/k10qu3ushCq/mqtt_stm32/thing/service/property/set 中订阅,点击开关按钮将收到消息:

image.png

ESP8266 固件烧录及串口调试

首先,固件烧录部分详看:ESP8266 烧写 AT MQTT 固件

ESP8266 连上串口后测试 AT 命令(记得加 \r\n):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 设置热点模式
AT+CWMODE=1

# 链接手机热点(或 WIFI)
AT+CWJAP="<热点名称>","<热点密码>"

# MQTT配置。注意,逗号前加反斜杠。ClientID+用户名+密码
AT+MQTTUSERCFG=0,1,"mqtt_stm32|securemode=2\,signmethod=hmacsha1\,timestamp=6606|","mqtt_stm32&k1xxxxxxxq","5DExxxxxxC2",0,0,""

# 连接 MQTT Broker
AT+MQTTCONN=0,"k1xxxxxxxq.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883,0

# 订阅 MQTT主题
AT+MQTTSUB=0,"/sys/k10qu3ushCq/mqtt_stm32/thing/service/property/set",0

# 发送数据
AT+MQTTPUB=0,"/sys/k10qu3ushCq/mqtt_stm32/thing/event/property/post","{\"params\":{\"temperature\":42\,\"Humidity\":22}\,\"version\":\"1.0.0\"}",0,0

指令说明参考:入门指南 - ESP32 - — ESP-AT 用户指南 latest 文档 (espressif.com)

测试发送时间上行成功后,可以继续测试 LED 开关命令。在 IoT Studio 点击按钮,串口助手将回显消息。

软件实现思路

整个 STM32 工程比较庞杂。本节介绍主要的具体思路,并展示重要代码过程。

主要思路:

  1. STM32 串口 1 用于向电脑发送数据,printf 重写为向串口 1 发送数据。详看:串口驱动程序之「发送数据」
  2. 串口 2 用于链接 ESP8266,需要实现不定长数据的收发。详看:串口驱动程序之「不定长字符串的接收」
  3. 使用 DHT11 检测环境温湿度。详看:DHT11 驱动程序
  4. OLED 模块作为温湿度数据的实时显示。详看:OLED 驱动程序
  5. 一个任务指示灯,单纯用来指示 FreeRTOS 任务有没有卡死
  6. 一个 LED 灯用来应答阿里云发来的数据

以下代码主要解析任务分配以及设备初始化的编写。标准库和 HAL 具体实现略有不同(LED 用的端口、不定长字符串接收的实现方式),请以具体配置为准。

标准库

main.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#include "stm32f10x.h"                  // Device header
#include "gpio_out.h"
#include "key.h"
#include "OLED.h"
#include "timer.h"
#include "SysTick.h"
#include "FreeRTOS.h"
#include "task.h"
#include <limits.h>
#include <string.h>
#include "dht11.h"
#include "esp8266.h"
#include "ALi_MQTT_Temp_Humi_LED_Device.h"

//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);


//任务优先级
#define LED5_TASK_PRIO 2
//任务堆栈大小
#define LED5_STK_SIZE 50
//任务句柄
TaskHandle_t LED5Task_Handler;
//任务函数
void led5_task(void *pvParameters);

//任务优先级
#define MAIN_TASK_PRIO 3
//任务堆栈大小
#define MAIN_STK_SIZE 50
//任务句柄
TaskHandle_t MainTask_Handler;
//任务函数
void main_task(void *pvParameters);

//任务优先级
#define WIFI_INIT_TASK_PRIO 4
//任务堆栈大小
#define WIFI_INIT_STK_SIZE 128
//任务句柄
TaskHandle_t WifiInitTask_Handler;
//任务函数
void wifi_init_task(void *pvParameters);

//任务优先级
#define WIFI_TASK_PRIO 5
//任务堆栈大小
#define WIFI_STK_SIZE 128
//任务句柄
TaskHandle_t WifiTask_Handler;
//任务函数
void wifi_task(void *pvParameters);

//任务优先级
#define TEST_ON_TASK_PRIO 6
//任务堆栈大小
#define TEST_ON_STK_SIZE 128
//任务句柄
TaskHandle_t TestOnTask_Handler;
//任务函数
void test_on_task(void *pvParameters);

//任务优先级
#define TEST_OFF_TASK_PRIO 6
//任务堆栈大小
#define TEST_OFF_STK_SIZE 128
//任务句柄
TaskHandle_t TestOffTask_Handler;
//任务函数
void test_off_task(void *pvParameters);

// LED灯
#define LED5 GPIO_Pin_5

// ESP8266 RESET
//#define ESP8266_RESET GPIO_Pin_7 // 低电平 reset


/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
GPIO_OUT_Init(LED5); // FreeRTOS任务指示灯

AMTHL_Init();


//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区

//创建任务指示灯任务
xTaskCreate((TaskFunction_t )led5_task,
(const char* )"led5_task",
(uint16_t )LED5_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED5_TASK_PRIO,
(TaskHandle_t* )&LED5Task_Handler);
//创建main任务
xTaskCreate((TaskFunction_t )main_task,
(const char* )"main_task",
(uint16_t )MAIN_STK_SIZE,
(void* )NULL,
(UBaseType_t )MAIN_TASK_PRIO,
(TaskHandle_t* )&MainTask_Handler);
//创建wifi任务
xTaskCreate((TaskFunction_t )wifi_init_task,
(const char* )"wifi_init_task",
(uint16_t )WIFI_INIT_STK_SIZE,
(void* )NULL,
(UBaseType_t )WIFI_INIT_TASK_PRIO,
(TaskHandle_t* )&WifiInitTask_Handler);

vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}



void led5_task(void *pvParameters)
{
while(1)
{
GPIO_OUT_Set(LED5,1);
vTaskDelay(200);

GPIO_OUT_Set(LED5,0);
vTaskDelay(800);

}
}

extern unsigned int rec_data[4];
void main_task(void *pvParameters)
{
while(1)
{
DHT11_REC_Data();
OLED_ShowNum(2,7,rec_data[2],2);
OLED_ShowNum(2,10,rec_data[3],2);
OLED_ShowNum(3,7,rec_data[0],2);
OLED_ShowNum(3,10,rec_data[1],2);
Delay_ms(2000);// 延时2s 否则DHT11数据不稳定
}
}

// 一次性任务
void wifi_init_task(void *pvParameters)
{

AMTHL_Connet();
xTaskCreate((TaskFunction_t )wifi_task,
(const char* )"wifi_task",
(uint16_t )WIFI_STK_SIZE,
(void* )NULL,
(UBaseType_t )WIFI_TASK_PRIO,
(TaskHandle_t* )&WifiTask_Handler);
xTaskCreate((TaskFunction_t )test_on_task,
(const char* )"test_on_task",
(uint16_t )TEST_ON_STK_SIZE,
(void* )NULL,
(UBaseType_t )TEST_ON_TASK_PRIO,
(TaskHandle_t* )&TestOnTask_Handler);
xTaskCreate((TaskFunction_t )test_off_task,
(const char* )"test_off_task",
(uint16_t )TEST_OFF_STK_SIZE,
(void* )NULL,
(UBaseType_t )TEST_OFF_TASK_PRIO,
(TaskHandle_t* )&TestOffTask_Handler);

vTaskDelete(WifiInitTask_Handler);
}

void wifi_task(void *pvParameters)
{
vTaskDelay(2000);

while(1)
{
AMTHL_SendMessage();
vTaskDelay(10000);
}
}

// 两个任务以防任务偏向
void test_on_task(void *pvParameters)
{
while(1)
{
if(AMTHL_LED_ON()) // 消除抖动
Delay_ms(1000);
vTaskDelay(50);
}
}

void test_off_task(void *pvParameters)
{
while(1)
{
if(AMTHL_LED_OFF()) // 消除抖动
Delay_ms(1000);
vTaskDelay(50);
}
}

设备:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include "stm32f10x.h"                  // Device header
#include "ALi_MQTT_Temp_Humi_LED_Device.h"

#include "serial.h"
#include "OLED.h"
#include "esp8266.h"
#include "SysTick.h"
#include "dht11.h"
#include "gpio_out.h"

#define WIFI_SSID "ssid"
#define WIFI_PASSWORD "ssidpswd"
#define MQTT_CLIENT_ID "mqtt_stm32|securemode=2\\,signmethod=hmacsha1\\,timestamp=106|"
#define MQTT_USER_NAME "mqtt_stm32&kxxxxCq"
#define MQTT_PASSWD "5DE3xxxxxxxxxEA4C2"
#define BROKER_ASDDRESS "kxxxxxCq.iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define SUB_TOPIC "/sys/kxxxxxq/mqtt_stm32/thing/service/property/set"
#define PUB_TOPIC "/sys/kxxxxxq/mqtt_stm32/thing/event/property/post"
#define JSON_FORMAT "{\\\"params\\\":{\\\"temperature\\\":%u\\,\\\"Humidity\\\":%u}\\,\\\"version\\\":\\\"1.0.0\\\"}"

#define SIGNAL_LED GPIO_Pin_6
#define MQTTPUB_BUF_SIZE 256
extern unsigned int rec_data[4]; // DHT11
extern USART_Buffer ESP8266_Buffer;
void AMTHL_Init(void){
OLED_Init();
Serial_Init(115200); // 波特率115200
ESP8266_Init(115200);
GPIO_OUT_Init(SIGNAL_LED);

OLED_Clear();
OLED_ShowString(1,1,"DHT11 Data");
OLED_ShowString(2,1,"Temp:");
OLED_ShowString(2,9,".");
OLED_ShowString(3,1,"Humi:");
OLED_ShowString(3,9,".");
}

void AMTHL_Connet(void){
printf("1. Set Station Mode.\r\n");
ESP8266_Cmd("AT+CWMODE=1","OK",500);
Delay_ms(1000);

printf("2. Close ESP8266 Echo.\r\n");
ESP8266_Cmd("ATE0","OK",500);
Delay_ms(1000);

printf("3. No Auto Connect WIFI.\r\n");
ESP8266_Cmd("AT+CWAUTOCONN=0\r\n","OK",500);
Delay_ms(1000);

printf("4. Start Connecting.\r\n");
ESP8266_Cmd("AT+CWJAP=\""WIFI_SSID"\",\"" WIFI_PASSWORD "\"","OK",200);
Delay_ms(5000);
ESP8266_Cmd("AT+MQTTUSERCFG=0,1,\"" MQTT_CLIENT_ID "\",\"" MQTT_USER_NAME "\",\"" MQTT_PASSWD "\",0,0,\"\"","OK",200);
Delay_ms(3000);
ESP8266_Cmd("AT+MQTTCONN=0,\"" BROKER_ASDDRESS "\",1883,0","OK",200);
Delay_ms(3000);
ESP8266_Cmd("AT+MQTTSUB=0,\"" SUB_TOPIC "\",0","OK",200);
Delay_ms(3000);
}

void AMTHL_SendMessage(void){
char buf[MQTTPUB_BUF_SIZE];
unsigned int temp,humi;
temp = rec_data[2];
humi = rec_data[0];
sprintf(buf,"AT+MQTTPUB=0,\"" PUB_TOPIC "\",\"" JSON_FORMAT "\",0,0",temp,humi);
ESP8266_Cmd(buf,"OK",200);

printf("Temp: %u degree, Humi: %u %%",temp,humi);
}

uint8_t AMTHL_LED_ON(void){
if (ESP8266_Buffer.FinishFlag){
if(ESP8266_Check_Str(ESP8266_Buffer.Body,"{\"LED\":1}")){
GPIO_OUT_Set(SIGNAL_LED,0); // 开灯
return 1;
}
}
return 0;
}

uint8_t AMTHL_LED_OFF(void){
if (ESP8266_Buffer.FinishFlag){
if(ESP8266_Check_Str(ESP8266_Buffer.Body,"{\"LED\":0}")){
GPIO_OUT_Set(SIGNAL_LED,1); // 关灯
return 1;
}
}
return 0;
}

HAL 库

任务配置:

image.png

freertos.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "OLED.h"
#include "dht11.h"
#include "usart.h"
#include "esp8266.h"
#include "ali_device.h"
/* USER CODE END Includes */


/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
extern uint8_t temperature;
extern uint8_t humidity;
/* USER CODE END Variables */

// 省略自动生成内容


void led_task_func(void *argument)
{
/* USER CODE BEGIN led_task_func */
/* Infinite loop */
for(;;)
{
// 任务指示灯
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
osDelay(200);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
osDelay(800);
}
/* USER CODE END led_task_func */
}


void detect_task_finc(void *argument)
{
/* USER CODE BEGIN detect_task_finc */

/* Infinite loop */
for(;;)
{
if(AMTHL_LED_ON())
osDelay(500);
if(AMTHL_LED_OFF())
osDelay(500);
osDelay(50);
}
/* USER CODE END detect_task_finc */
}


void ali_mqtt_task_func(void *argument)
{
/* USER CODE BEGIN ali_mqtt_task_func */
AMTHL_Connet();
/* Infinite loop */
for(;;)
{
// 顺带显示
DHT11_Read_Data(&humidity,&temperature);
OLED_ShowNum(2,7,temperature,2);
OLED_ShowNum(3,7,humidity,2);
AMTHL_SendMessage();
osDelay(2000);
}
/* USER CODE END ali_mqtt_task_func */
}

设备:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

#include "cmsis_os.h"
#include "usart.h"
#include "esp8266.h"
#include "dht11.h"

#include "OLED.h"

#include "ali_device.h"

#define WIFI_SSID "ssid"
#define WIFI_PASSWORD "ssidpswd"
#define MQTT_CLIENT_ID "mqtt_stm32|securemode=2\\,signmethod=hmacsha1\\,timestamp=106|"
#define MQTT_USER_NAME "mqtt_stm32&kxxxxCq"
#define MQTT_PASSWD "5DE3xxxxxxxxxEA4C2"
#define BROKER_ASDDRESS "kxxxxxCq.iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define SUB_TOPIC "/sys/kxxxxxq/mqtt_stm32/thing/service/property/set"
#define PUB_TOPIC "/sys/kxxxxxq/mqtt_stm32/thing/event/property/post"
#define JSON_FORMAT "{\\\"params\\\":{\\\"temperature\\\":%u\\,\\\"Humidity\\\":%u}\\,\\\"version\\\":\\\"1.0.0\\\"}"


#define MQTTPUB_BUF_SIZE 256
char buf[MQTTPUB_BUF_SIZE];

extern uint8_t temperature;
extern uint8_t humidity;

//#define MQTTPUB_BUF_SIZE 256

//extern unsigned int rec_data[4]; // DHT11
//extern USART_Buffer ESP8266_Buffer;
void AMTHL_Init(void){
OLED_Clear();
OLED_ShowString(1,1,"DHT11");
OLED_ShowString(2,1,"temp:");
OLED_ShowString(2,10,"^C");
OLED_ShowString(3,1,"humi:");
OLED_ShowString(3,10,"%");

}

void AMTHL_Connet(void){
printf("1. Set Station Mode.\r\n");
ESP8266_Cmd((uint8_t*)"AT+CWMODE=1",(uint8_t*)"OK",100);
osDelay(100);

printf("2. Close ESP8266 Echo.\r\n");
ESP8266_Cmd((uint8_t*)"ATE0",(uint8_t*)"OK",100);
osDelay(100);

printf("3. No Auto Connect WIFI.\r\n");
ESP8266_Cmd((uint8_t*)"AT+CWAUTOCONN=0\r\n",(uint8_t*)"OK",500);
osDelay(100);

printf("*** Start Connecting. ***\r\n");
ESP8266_Cmd((uint8_t*)"AT+CWJAP=\""WIFI_SSID"\",\"" WIFI_PASSWORD "\"",(uint8_t*)"OK",1000);
osDelay(5000);
ESP8266_Cmd((uint8_t*)"AT+MQTTUSERCFG=0,1,\"" MQTT_CLIENT_ID "\",\"" MQTT_USER_NAME "\",\"" MQTT_PASSWD "\",0,0,\"\"",(uint8_t*)"OK",200);
osDelay(3000);
ESP8266_Cmd((uint8_t*)"AT+MQTTCONN=0,\"" BROKER_ASDDRESS "\",1883,0",(uint8_t*)"OK",200);
osDelay(3000);
ESP8266_Cmd((uint8_t*)"AT+MQTTSUB=0,\"" SUB_TOPIC "\",0",(uint8_t*)"OK",200);
osDelay(3000);
}

void AMTHL_SendMessage(void){

sprintf(buf,"AT+MQTTPUB=0,\"" PUB_TOPIC "\",\"" JSON_FORMAT "\",0,0",temperature,humidity);
ESP8266_Cmd((uint8_t*)buf,(uint8_t*)"OK",200);

printf("Temp: %u degree, Humi: %u %%",temperature,humidity);
}

uint8_t AMTHL_LED_ON(void){
if (UART2_Rx_flg){
if(ESP8266_Check_Str(RxBuf,(uint8_t*)"{\"LED\":1}")){
HAL_GPIO_WritePin(GPIOA,SIGNAL_LED,(GPIO_PinState)0); // 开灯
return 1;
}
}
return 0;
}

uint8_t AMTHL_LED_OFF(void){
if (UART2_Rx_flg){
if(ESP8266_Check_Str(RxBuf,(uint8_t*)"{\"LED\":0}")){
HAL_GPIO_WritePin(GPIOA,SIGNAL_LED,(GPIO_PinState)1); // 关灯
return 1;
}
}
return 0;
}

后记

工程实践被🍐🏮训斥了…😎😎😎。

本文参考