飛書文檔https://x509p6c8to.feishu.cn/wiki/WFmqwImDViDUezkF7ercZuNDnve
一、WiFi模組應用
當設備需要連接網絡,實現遠程控制,狀態監控時,就需要添加通信模組,常見的通信模組WiFi模組、2G模組、4G模組等:
| | |
我們的板卡上沒有直接用現成的模組,而是直接把WiFi芯片設計到板卡上:
| |
所以,我們就可以基于這個芯片嘗試做聯網的應用。
因為我們用的是原廠芯片的方案,所以WiFi芯片內是沒有程序的,我們需要先到官方下載WiFi的固件進行燒錄,燒錄成功后,才能用串口驅動WiFi芯片。
二、WiFi模組固件燒錄
AT指令是什么?
ESP-AT 是樂鑫開發的可直接用于量產的物聯網應用固件,旨在降低客戶開發成本,快速形成產品。通過 ESP-AT 指令,您可以快速加入無線網絡、連接云平臺、實現數據通信以及遠程控制等功能,真正的通過無線通訊實現萬物互聯。
固件下載
官方AT固件下載(ESP8266是樂鑫的方案)
https://docs.espressif.com/projects/esp-at/en/release-v2.2.0.0_esp8266/AT_Binary_Lists/ESP8266_AT_binaries.html
安信可固件下載(安信可是ESP8266模組廠商)
https://docs.ai-thinker.com/%E5%9B%BA%E4%BB%B6%E6%B1%87%E6%80%BB
建議直接下載下方固件即可:參考飛書文檔
燒錄接線
下載AT指令固件到本地后,我們需要先按下方接好線,DC電源頭供電,核心板不接,然后只接TX RX GND
部分小伙伴出現電腦USB供電不足導致燒錄失敗或亂碼、無應答問題,可以嘗試獨立供電,如下圖:
- 1、拆除STM32核心板,因為STM32的TX RX和WiFi的共用,避免有數據干擾。
- 2、USB轉TTL模塊只需要接TXD、RXD、GND到板卡,注意3V3不需要接
- 3、接上電源適配器,按復位按鍵即可進入燒錄(注意燒錄模式短接MODE的插針,運行模式斷開)
注意,如果使用外部DC頭供電,下方的3.3V紅色線就不需要接了。
如果接線正常,我們可以在電腦的設備管理器中,可以看到新出現的COM口,每臺電腦不一樣,可以查看下自己電腦的COM口,下方燒錄需要用到。
燒錄軟件使用
需要使用樂鑫提供的flash_download_tool工具進行固件燒錄,下載鏈接如下。
https://www.espressif.com.cn/zh-hans/support/download/other-tools
[flash_download_tool_3.9.2_0.zip]
下載后直接解壓即用,運行燒錄工具中的.exe文件,選擇型號,選擇ESP8266
打開燒錄軟件,
從"…“選擇要燒錄的bin文件: xxxESP8266-AT_MQTT-xM.bin,上面下載的固件。
填寫燒錄地址"0x0”,然后勾選固件前面的√,很重要;
SPI MODE選擇 “DOUT”;
"DoNotChgBin"不變;
“COM” 選擇你電腦的COM口;
波特率默認即可。
上述配置完成后, 點擊下方START開始燒錄,若一直停在等待上電同步,可以點擊板卡的RES按鈕,就可以開始下載了,下載一般20s左右,如果1S內完成的,一般是上面沒勾選,如果長時間沒下載完,一般是線有問題,可以換杜邦線重新接穩。
| |
下載完成后,拔掉J10的IO0的杜邦線,從下載模式切換到運行模式,打開串口助手,設置波特率115200 8 N 1,按RES按鈕,就可以看到設備啟動數據,注意
需要接上電源&打開開關,能看到如下打印
到這里,模組燒錄就已經完成啦
注意:
部分小伙伴出現電腦USB供電不足導致燒錄失敗或亂碼問題,可以嘗試獨立供電,如下圖:
- 1、拆除STM32核心板,因為STM32的TX RX和WiFi的共用,避免有數據干擾。
- 2、USB轉TTL模塊只需要接TXD、RXD、GND到板卡,注意3V3不需要接
- 3、接上電源適配器,按復位按鍵即可進入燒錄(注意燒錄模式短接MODE的插針,運行模式斷開)
| |
三、阿里云物聯網云平臺
我們WiFi準備好后,
還需要有個路由器,方便WiFi模組連接外網,也可以開手機熱點。
最后,還需要有個云服務器做遠程控制,或者上報設備狀態。
云服務器廠家有很多
阿里云物聯網
騰訊物聯網
中移動物聯網
機智云等等
注意:
由于近期阿里云暫停個人賬號開通物聯網平臺,為了方便大家做實驗,這里開放幾個測試賬號給大家使用
阿里云物聯網共享賬號 目前只提供購買板卡小伙伴學習使用,可以從旺旺給你發送的資料鏈接中獲取密碼。
共享賬號已經創建了產品,大家可以拷貝創建好的設備的MQTT連接參數直接使用,然后直接查看第四章。
課程使用阿里云物聯網平臺,需要我們注冊登錄下,下方是步驟
https://www.aliyun.com/
點擊管理控制臺
如果提示未開通,點擊開通即可,測試使用是免費的。
選擇公共實例,然后鼠標點擊“公共實例”進入。
如果尚未開通,需要先進行開通,開通時間一般5min內
創建一個新的產品。
填寫產品名稱、所屬品類等必要信息,并完成產品創建步驟。
這里我們選擇創建一個溫濕度檢測產品,產品將會影響到后續的通信協議字段。
在創建完成的產品頁面上,點擊添加設備。
輸入設備名稱并確認。
至此,阿里云物聯網平臺創建設備完成。進入設備詳情頁,查看MQTT連接參數,并進行保存。
至此,平臺部分配置完成,
這些參數將用于在ESP-01S / ESP8266上配置AT指令,實現設備與物聯網平臺之間的通信。
{"clientId":"k0rqhbzuJeE.device1|securemode=2,signmethod=hmacsha256,timestamp=1705652029669|","username":"device1&k0rqhbzuJeE","mqttHostUrl":"iot-06z00dcx1hvlwd3.mqtt.iothub.aliyuncs.com","passwd":"f3c17488453a737afd24edefdd4ec6862848a0ca2f8866b7015f5787b90e68a2","port":1883}
四、配置WiFi模組連接云平臺
連接阿里云服務器
阿里云使用MQTT協議
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議),是一種基于發布/訂閱(publish/subscribe)模式的“輕量級”通訊協議,該協議構建于TCP/IP協議上,由IBM在1999年發布。
MQTT最大優點在于,用極少的代碼和有限的帶寬,為連接遠程設備提供實時可靠的消息服務。
作為一種低開銷、低帶寬占用的即時通訊協議,使其在物聯網、小型設備、移動應用等方面有較廣泛的應用。MQTT 與 HTTP 一樣,MQTT 運行在傳輸控制協議/互聯網協議 (TCP/IP) 堆棧之上。
wifi連接服務器用哪種協議?
TCP:比較原始,需要自己擴展的功能較多,開發效率低
HTTP:比較重,網頁端的協議,占用的帶寬較大。
MQTT:適用于物聯網設備和傳感器等低帶寬、不穩定網絡環境下的通信。MQTT的特性
-協議心跳包僅兩個字節
-協議支持QoS(服務質量)設置,可以確保消息傳輸的可靠性。
QoS 0:最多一次傳輸。消息發布者只發送一次消息,不考慮它是否被接收。這種傳輸方式是最快的,但也是最不可靠的,因為消息可能會丟失。
QoS 1:至少一次傳輸。消息發布者會發送消息并等待確認,如果確認未收到,則會重發消息。這種傳輸方式可以保證消息最少被傳輸一次,但可能會重復傳輸。
QoS 2:恰好一次傳輸。消息發布者會發送消息并等待確認,如果確認未收到,則會重發消息。接收者會對消息進行去重和重復檢查,以確保消息只被傳輸一次。這種傳輸方式是最可靠的,但也是最慢的。
-協議支持發布/訂閱模式,可以根據應用場景選擇不同的模式。
-可擴展設備影子模式
我們模組固件是支持MQTT的,我們可以使用串口AT配置模組連接云平臺
這里用安信可官方提供的串口助手,調試更加便捷:參考飛書文檔
AT指令如下:
連接阿里云AT指令介紹
AT+CWMODE=3 設置ESP模塊為Station+SoftAP模式;
AT+CWJAP="SSID","PWD" 設置ESP模塊連接無線網絡 *注意雙引號為英文;
AT+MQTTUSERCFG=0,1,"NULL","username","password",0,0,"" MQTT用戶屬性,username和passwd與下圖對應
AT+MQTTCLIENTID=0,"clientId" 設置MQTT 的clientId參數;clientId也與下圖對應
AT+MQTTCONN=0,"host",1883,1 連接 MQTT Broker;host與下圖mqttHostUrl對應。
AT+MQTTCLEAN 斷開MQTT連接。
AT+RST 復位ESP-01S / ESP8266模塊;
需要注意AT+MQTTCLIENTID指令中的clientId中的逗號前需要加\符號進行轉義,
假設clientId為"xxx|securemode=2,signmethod=hmacsha256,timestamp=xxx|",
那么AT指令應為AT+MQTTCLIENTID=0,"xxx|securemode=2\,signmethod=hmacsha256\,timestamp=xxx|"下方是我賬號的設備信息,可以參考下,替換為自己平臺的信息:
AT+CWMODE=3
AT+CWJAP="leo","123456789"
AT+MQTTUSERCFG=0,1,"NULL","device1&kxxxxxxJeE","f3c17488453a7xxxxxxx015f5787b90e68a2",0,0,""
AT+MQTTCLIENTID=0,"k0rqhxxxxeE.device1|securemode=2\,signmethod=hmacsha256\,timestamp=1705652029669|"
AT+MQTTCONN=0,"iot-06z0xxxxxxlwd3.mqtt.iothub.aliyuncs.com",1883,1更多AT指令可以參考官方文檔
https://docs.espressif.com/projects/esp-at/en/release-v2.2.0.0_esp8266/Get_Started/index.html
發送完以上指令后,在阿里云物聯網平臺中刷新設備網頁,你將會看到設備已成功上線的信息。
狀態上報-發布
回到平臺的產品界面,點擊Topic類列表,點擊物模型通信,可以看到你自己的狀態上報Topic
/sys/xxxx/${deviceName}/thing/event/property/post
然后看下我們這個產品的功能定義中,有哪些需要上報的字段
這里,我們使用當前溫度為例,記錄標識符CurrentTemperature,當然,我們也可以點擊“編輯”添加、刪除、修改功能模塊。
拿到標識符后,我們就可以通過下方MQTT指令上報狀態
AT+MQTTPUB=0,"topic字段","data字段",1,0 通過 topic 發布 MQTT消息特別注意,空格,英文符號
注意,topic中的deviceName改為你創建的設備名稱:
AT+MQTTPUB=0,"/sys/k0rqhbzuJeE/device1/thing/event/property/post","{\"params\":{\"CurrentTemperature\":33}}",1,0
然后,我們就可以在設備界面看到上報的溫度數據啦:
控制接收-訂閱
回到平臺的產品界面,點擊Topic類列表,點擊物模型通信,可以看到你自己的設備設置的Topic
/sys/k0rqhbzuJeE/${deviceName}/thing/service/property/set
然后通過串口調試助手訂閱主題
AT+MQTTSUB=0,"topic字段",1? 訂閱指定 MQTT topic特別注意,空格,英文符號
AT+MQTTSUB=0,"/sys/k0rqhbzuJeE/device1/thing/service/property/set",1
然后我們可以增加一個開關控制字段
我們隨便添加一個支持讀寫的屬性,也可以自己自定義
記得點擊發布上線
發布成功后,我們可以模擬手機端操作這個字段,發送控制指令給模組。
修改對應屬性,點擊設置
然后我們就可以在串口調試助手看到接收的指令
五、STM32驅動WiFi模組
前面我們都是使用串口助手發送指令驅動WiFi模組的,那接下來,我們就可以用STM32替換串口助手驅動WiFi模組啦。
開始這個章節時,可以把下方USB轉串口部分拔掉。
這部分的原理圖是這樣的,因為模組使用串口通信,所以我們只需要關注PC10和PC11的USART3。
創建工程,打開UART4
同時,開啟串口中斷
配置DMA
調整DMA初始化順序(重要)
為了更直觀看到設備運行狀態,打開USART1作為日志口。
生成工程,然后參考串口章節,添加日志打印重定向
main.c
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes *//* USER CODE BEGIN 2 */printf("app init\n");/* USER CODE END 2 *//* USER CODE BEGIN 4 */
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);return ch;
}
添加最簡單的AT指令發送和接收判斷,通過串口中斷+DMA不定長接收
main.c
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
/* USER CODE END Includes *//* USER CODE BEGIN 0 */
#define AT "AT\r\n"
#define ACK_OK "OK"
#define BUFFER_SIZE 256uint8_t rx_buf[BUFFER_SIZE];? //應用處理buffer
bool rx_status = false;
extern DMA_HandleTypeDef hdma_uart4_rx;
uint8_t dma_rxbuf[BUFFER_SIZE];?????????????????????????????????????? //DMA接收bufferstatic void init(void);
/* USER CODE END 0 *//* USER CODE BEGIN 2 */printf("app init\n");__HAL_UART_ENABLE_IT(&huart4,UART_IT_IDLE);HAL_UART_Receive_DMA(&huart4,dma_rxbuf,sizeof(dma_rxbuf));init();/* USER CODE END 2 *//* USER CODE BEGIN 4 */
void copy_to_rx_buf(uint8_t *ack,uint8_t len){if(rx_status)return;if(len > sizeof(rx_buf))return;memcpy(rx_buf,ack,len);rx_status = true;
}bool send_cmd(uint8_t *cmd,uint8_t *ack){int time_out = 500;memset(rx_buf,0,sizeof(rx_buf));printf("send ----> %s\n",cmd);HAL_UART_Transmit_DMA(&huart4 , (uint8_t *)cmd, strlen((const char *)cmd));while (time_out --){if(rx_status){printf("read ----> %s\n",rx_buf);if(strstr((const char*)rx_buf,(const char*) ack) != NULL){printf("ack ok\n");rx_status = false;return true;}memset(rx_buf,0,sizeof(rx_buf));rx_status = false;}HAL_Delay(10);}printf("ack fail\n");return false;
}void init(){send_cmd((uint8_t *)AT,(uint8_t *)ACK_OK);HAL_Delay(500);
}void UART_IDLEHandler(){if(__HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE) == SET) //如果串口處于空閑狀態{__HAL_UART_CLEAR_FLAG(&huart4, UART_FLAG_IDLE);//清空空閑狀態標志HAL_UART_DMAStop(&huart4); //關閉DMA傳輸//計算接收到的數據長度 ,已接收長度=需要接收總長度-剩余待接收長度uint8_t rlen = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_uart4_rx);//進行數據處理????copy_to_rx_buf(dma_rxbuf,rlen);//重新打開DMA接收HAL_UART_Receive_DMA(&huart4,dma_rxbuf,sizeof(dma_rxbuf));???????????????}
}int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);return ch;
}
/* USER CODE END 4 */mian.h
/* USER CODE BEGIN EFP */
void UART_IDLEHandler(void);
/* USER CODE END EFP */stm32f1xx_it.c
void UART4_IRQHandler(void)
{/* USER CODE BEGIN UART4_IRQn 0 *//* USER CODE END UART4_IRQn 0 */HAL_UART_IRQHandler(&huart4);/* USER CODE BEGIN UART4_IRQn 1 */UART_IDLEHandler();/* USER CODE END UART4_IRQn 1 */
}
燒錄運行:
工程參考飛書文檔
然后我們可以所有初始化AT指令全部加上,并且發布和訂閱對應消息,最終實現溫度上報和控制指令接收的功能。
最終版本的main.c如下
/* USER CODE BEGIN Header */
/********************************************************************************* @file?????????? : main.c* @brief????????? : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* 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 */
#define AT "AT\r\n"
#define AT_WIFI_MODE "AT+CWMODE=3\r\n"
#define AT_SET_PSW "AT+CWJAP=\"Kang\",\"555883200\"\r\n"
#define AT_SET_MQTT_CFG "AT+MQTTUSERCFG=0,1,\"NULL\",\"device1&k0rqhbzuJeE\",\"f3c17488453a737afd24edefdd4ec6862848a0ca2f8866b7015f5787b90e68a2\",0,0,\"\"\r\n"
#define AT_SET_MQTT_CLENTID "AT+MQTTCLIENTID=0,\"k0rqhbzuJeE.device1|securemode=2\\,signmethod=hmacsha256\\,timestamp=1705652029669|\"\r\n"
#define AT_SET_MQTT_CONN "AT+MQTTCONN=0,\"iot-06z00dcx1hvlwd3.mqtt.iothub.aliyuncs.com\",1883,1\r\n"
#define AT_MQTT_SUB "AT+MQTTSUB=0,\"/sys/k0rqhbzuJeE/device1/thing/service/property/set\",1\r\n"
#define AT_MQTT_PUB "AT+MQTTPUB=0,\"/sys/k0rqhbzuJeE/device1/thing/event/property/post\",\"{\\\"params\\\":{\\\"CurrentTemperature\\\":%d}}\",1,0\r\n"
#define ACK_OK "OK"#define BUFFER_SIZE 256uint8_t rx_buf[BUFFER_SIZE];? //應用處理buffer
uint8_t tx_buf[BUFFER_SIZE];? //發送buffer
bool rx_status = false;extern DMA_HandleTypeDef hdma_uart4_rx;
uint8_t dma_rxbuf[BUFFER_SIZE];?????????????????????????????????????? //DMA接收bufferstatic void init(void);
static bool send_cmd(uint8_t *cmd,uint8_t *ack);
static void read_cmd(void);
/* USER CODE END 0 *//*** @brief? The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* 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_DMA_Init();MX_USART1_UART_Init();MX_UART4_Init();/* USER CODE BEGIN 2 */printf("app init\n");__HAL_UART_ENABLE_IT(&huart4,UART_IT_IDLE);HAL_UART_Receive_DMA(&huart4,dma_rxbuf,sizeof(dma_rxbuf));init();printf("wifi init finish\n");uint8_t temperature = 20;uint8_t send_count = 0;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */send_count ++;if(send_count >= 10){//10s上報一條send_count = 0;sprintf((char *)tx_buf,"AT+MQTTPUB=0,\"/sys/k0rqhbzuJeE/device1/thing/event/property/post\",\"{\\\"params\\\":{\\\"CurrentTemperature\\\":%d}}\",1,0\r\n", temperature);send_cmd(tx_buf,(uint8_t *)ACK_OK);temperature ++;if(temperature > 100)temperature = 20;}read_cmd();HAL_Delay(1000);}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 */void copy_to_rx_buf(uint8_t *ack,uint8_t len){if(rx_status)return;if(len > sizeof(rx_buf))return;memcpy(rx_buf,ack,len);rx_status = true;
}bool send_cmd(uint8_t *cmd,uint8_t *ack){int time_out = 500;memset(rx_buf,0,sizeof(rx_buf));printf("send ----> %s\n",cmd);HAL_UART_Transmit_DMA(&huart4 , (uint8_t *)cmd, strlen((const char *)cmd));while (time_out --){if(rx_status){printf("read ----> %s\n",rx_buf);if(strstr((const char*)rx_buf,(const char*) ack) != NULL){printf("ack ok\n");rx_status = false;return true;}memset(rx_buf,0,sizeof(rx_buf));rx_status = false;}HAL_Delay(10);}printf("ack fail\n");return false;
}void read_cmd(){if(rx_status){printf("read ----> %s\n",rx_buf);rx_status = false;}
}void init(){send_cmd((uint8_t *)AT,(uint8_t *)ACK_OK);HAL_Delay(500);send_cmd((uint8_t *)AT_WIFI_MODE,(uint8_t *)ACK_OK);HAL_Delay(500);send_cmd((uint8_t *)AT_SET_PSW,(uint8_t *)ACK_OK);HAL_Delay(500);send_cmd((uint8_t *)AT_SET_MQTT_CFG,(uint8_t *)ACK_OK);HAL_Delay(500);send_cmd((uint8_t *)AT_SET_MQTT_CLENTID,(uint8_t *)ACK_OK);HAL_Delay(500);send_cmd((uint8_t *)AT_SET_MQTT_CONN,(uint8_t *)ACK_OK);HAL_Delay(500);send_cmd((uint8_t *)AT_MQTT_SUB,(uint8_t *)ACK_OK);HAL_Delay(500);
}void UART_IDLEHandler(){if(__HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE) == SET) //如果串口處于空閑狀態{__HAL_UART_CLEAR_FLAG(&huart4, UART_FLAG_IDLE);//清空空閑狀態標志HAL_UART_DMAStop(&huart4); //關閉DMA傳輸//計算接收到的數據長度 ,已接收長度=需要接收總長度-剩余待接收長度uint8_t rlen = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_uart4_rx);//進行數據處理????copy_to_rx_buf(dma_rxbuf,rlen);//重新打開DMA接收HAL_UART_Receive_DMA(&huart4,dma_rxbuf,sizeof(dma_rxbuf));???????????????}
}int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);return ch;
}/* USER CODE END 4 *//*** @brief? This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef? USE_FULL_ASSERT
/*** @brief? Reports the name of the source file and the source line number*???????? where the assert_param error has occurred.* @param? file: pointer to the source file name* @param? line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
設備連接平臺成功后,每間隔10s上報一次溫度數據
在云平臺設置燈開關,設備也會收到消息
工程參考:飛書文檔
上面的工程僅僅使用數據復制的方式進行拷貝處理,當交互頻繁時,可能會出現丟失指令的情況,下方的工程使用環形緩沖區,可以避免指令丟失情況。
參考飛書文檔
手機APP開發參考
采用MQTT協議實現Android APP與阿里云平臺的連接_android連接mqtt 阿里云