标题直接 Buff 点满…
阅读指引
如果你是 0 基础选手,建议先阅读以下内容掌握基本的 FreeRTOS 工程知识:
C 语言基本语法
STM32 工程创建,详看
FreeRTOS 的移植,详看
本文主要分为三个部分,每个部分需要准备的工具如下:
阿里云物联网平台注册:需要阿里云账号。
模拟 MQTT 客户端发送与订阅消息:软件 MQTT.fx,阿里云提供的 MQTT_Password 工具。
ESP8266 固件烧录:串口助手软件,需要材料 ESP8266、USB-TTL、杜邦线若干。
软件实现:Keil 软件、STM32CubeMX(使用 HAL)、STM32、DHT11、杜邦线若干、OLED(可选)、LED 灯、ST-Link
阅读前的提示
阿里云相关产品新用户只能免费试用 1 个月。比如物联网企业版实例新用户可以试用 1 个月,但也有公共实例永久免费使用 。增值服务 IoT Studio 用于绘制可视化界面,可以试用 1 个月,但其实这也不是必须的 ,就是提供了一个可视化界面而已。
MQTT 功能是通过固件烧录进ESP8266中的,不是 MQTT 协议在 FreeRTOS 上的移植。
如果只是单纯实现温湿度监控及点灯的话,FreeRTOS 其实不是必须的。
接线图与实物图展示
Visio 随便画的,感觉掌握不到诀窍,很难画。
下图有个多余连接的串口,读者可以忽略。
UML
如果 UML 图不规范请指出哈。我感觉 UML 图我永远画不对…
用例图:
用户通过阿里云物联网平台进行温湿度数据监测以及 LED 灯控制,此外,用户还可通过直接观察设备显示屏读取温湿度监测数据。对于通过阿里云物联网平台监测温湿度数据的用例,除了在远程平台实现可视化界面外,STM32 需实现将温湿度数据发送至远程平台的能力。无论是温湿度数据的本地展示或远程发送,都依赖于 STM32 中获取温湿度数据用例。该用例需要 STM32 与温湿度监测设备进行数据交互。远程平台中控制 LED 灯用例的实现不仅依赖于物联网平台提供的指令发送接口,也需要 STM32 实现信号的接收与 LED 灯设置的功能。
发送温湿度过程顺序图:
单片机从监测设备获取温湿度数据并发送至阿里云物联网平台过程的顺序图如上图所示。单片机初始化完毕后,利用 FreeRTOS 任务函数定时向 DHT11 发送复位信号。DHT11 接收复位信号后将 40 Bit 的检测数据通过单总线协议传输至 STM32 处理。随后,STM32 利用该数据完成以下任务:
更新 OLED 显示屏,实现设备实时显示温湿度信息的功能。
将温湿度数据生成 AT 命令,通过串口发送至 ESP8266 模块中。
ESP8266 模块接收到 AT 指令后,将通过 MQTT 协议向阿里云物联网平台发布消息。阿里云物联网平台将根据该消息的主题与参数,更新可视化界面的网络应用,从而实现用户远程监控设备的功能。
接收 LED 灯指令顺序图:
用户通过网络应用的可视化界面控制设备 LED 灯的顺序图如上图所示。用户通过可视化界面操作 LED 灯状态为“0(关闭)”或“1(开启)”。MQTT Broker 向设备发送消息,该消息由连接至 STM32 单片机的 WIFI 模块接收。WIFI 模块将接收到的数据存放在串口缓冲区中,并设置标志位提醒 STM32 单片机进行接收。STM32 利用 FreeRTOS 任务调度,获取 WIFI 模块返回的信息并解析 LED 灯控制指令。最后根据指令控制 LED 灯电路,改变灯的状态。
阿里云物联网平台
此部分可参考官方文档:如何快速将设备接入物联网平台并控制其开关_物联网平台(IoT)-阿里云帮助中心 (aliyun.com)
添加产品物模型
首先你得拥有一个阿里云账号,然后开通物联网平台:
进入管理控制台:
创建一个实例(前提需实名认证):
标准实例可以免费开通试用 1 个月。
公共实例开通免费,但据说可能联网不佳,我试了一下感觉还行,没条件的可以直接使用公共实例。
进入实例详情:
创建一个产品:
创建设备:
下面添加一个物模型:
使用 IoT Studio 绘制界面
回到物联网平台,查看增值服务。如果没有 IoT Studio,可以在选购增值服务中购买。IoT Studio 可以试用 1 个月。
进入 IoT Studio,选择你的实例,新建 Web 应用:
绘制一个像样的页面:
仪表盘数据源配置:
折线图数据源配置:
按钮交互配置:
这时点击预览的话仪表盘会显示没有数据,可继续下一章节阅读。
MQTT.fx 模拟客户端发布与订阅消息
此部分可参考文档:使用MQTT协议模拟设备快速接入物联网平台_物联网平台(IoT)-阿里云帮助中心 (aliyun.com)
安装 MQTT_Password 工具包:如何计算MQTT签名参数_物联网平台(IoT)-阿里云帮助中心 (aliyun.com)
安装 MQTT.fx:MQTT.fx® Download (softblade.de)
回到阿里云物联网平台控制台>设备>查看,把三元素复制下来:
使用 MQTT_Password 计算签名:
除了此处的 Clientid 是需要填入的设备信息 Clientid,其他所有地方说的 Client ID 都是指 MQTT 连接的 Client ID 具体值就是计算结果的 mqttClientid
打开 MQTT.fx,配置:
Broker Address 为你的 ProductID
+.iot-as-mqtt.cn-shanghai.aliyuncs.com
。
链接。然后尝试发布消息和订阅消息:
连接后阿里云物联网平台将显示在线:
尝试在 /sys/k10qu3ushCq/mqtt_stm32/thing/event/property/post
发布一个 json 数据:
1 { "params" : { "temperature" : 42 , "Humidity" : 22 } , "version" : "1.0.0" }
结果在 IoT Studio 网页应用就会显示数据:
在 /sys/k10qu3ushCq/mqtt_stm32/thing/service/property/set
中订阅,点击开关按钮将收到消息:
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 AT+CWJAP="<热点名称>" ,"<热点密码>" AT+MQTTUSERCFG=0,1,"mqtt_stm32|securemode=2\,signmethod=hmacsha1\,timestamp=6606|" ,"mqtt_stm32&k1xxxxxxxq" ,"5DExxxxxxC2" ,0,0,"" AT+MQTTCONN=0,"k1xxxxxxxq.iot-as-mqtt.cn-shanghai.aliyuncs.com" ,1883,0 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 工程比较庞杂。本节介绍主要的具体思路,并展示重要代码过程。
主要思路:
STM32 串口 1 用于向电脑发送数据,printf
重写为向串口 1 发送数据。详看:串口驱动程序之「发送数据」
串口 2 用于链接 ESP8266,需要实现不定长数据的收发。详看:串口驱动程序之「不定长字符串的接收」
使用 DHT11 检测环境温湿度。详看:DHT11 驱动程序
OLED 模块作为温湿度数据的实时显示。详看:OLED 驱动程序
一个任务指示灯,单纯用来指示 FreeRTOS 任务有没有卡死
一个 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" #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) ;#define LED5 GPIO_Pin_5 int main () { SysTick_Init(72 ); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); GPIO_OUT_Init(LED5); 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); 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); 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 ); } } 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" #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 ]; extern USART_Buffer ESP8266_Buffer;void AMTHL_Init (void ) { OLED_Init(); Serial_Init(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 库
任务配置:
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 #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os.h" #include "OLED.h" #include "dht11.h" #include "usart.h" #include "esp8266.h" #include "ali_device.h" extern uint8_t temperature; extern uint8_t humidity; void led_task_func (void *argument) { for (;;) { HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13); osDelay(200 ); HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13); osDelay(800 ); } } void detect_task_finc (void *argument) { for (;;) { if (AMTHL_LED_ON()) osDelay(500 ); if (AMTHL_LED_OFF()) osDelay(500 ); osDelay(50 ); } } void ali_mqtt_task_func (void *argument) { AMTHL_Connet(); for (;;) { DHT11_Read_Data(&humidity,&temperature); OLED_ShowNum(2 ,7 ,temperature,2 ); OLED_ShowNum(3 ,7 ,humidity,2 ); AMTHL_SendMessage(); osDelay(2000 ); } }
设备:
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; 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 ; }
后记
工程实践被🍐🏮训斥了…😎😎😎。
本文参考