当前位置: 首页 > web >正文

单片机-STM32部分:18、WiFi模组

飞书文档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. 1、拆除STM32核心板,因为STM32的TX RX和WiFi的共用,避免有数据干扰。
  2. 2、USB转TTL模块只需要接TXD、RXD、GND到板卡,注意3V3不需要接
  3. 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. 1、拆除STM32核心板,因为STM32的TX RX和WiFi的共用,避免有数据干扰。
  2. 2、USB转TTL模块只需要接TXD、RXD、GND到板卡,注意3V3不需要接
  3. 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指令上报状态

C
AT+MQTTPUB=0,"topic字段","data字段",1,0 通过 topic 发布 MQTT消息

特别注意,空格,英文符号
注意,topic中的deviceName改为你创建的设备名称:
AT+MQTTPUB=0,"/sys/k0rqhbzuJeE/d
evice1/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 阿里云

http://www.xdnf.cn/news/6637.html

相关文章:

  • 真题卷001——算法备赛
  • 小结:JavaScript 模块化工具链
  • 傅里叶变换实战:图像去噪与边缘提取
  • 锚点跳转跟踪#
  • Web-CSS入门
  • ci/cd全流程实操
  • 2025年全国青少年信息素养大赛复赛集训(2):寻找250(题目及解析)
  • Perl测试起步:从零到精通的完整指南
  • 【Python】【OCR识别】 提取图片文字并根据内容智能分类存储
  • C#运算符
  • 大语言模型与多模态模型比较
  • 【笔记】cri-docker.service和containerd
  • 特斯拉虚拟电厂:能源互联网时代的分布式革命
  • [IMX] 01.IVT 表长度计算
  • 考研408《计算机组成原理》复习笔记,第二章(2)数值数据的表示(浮点数篇)
  • 【springboot项目服务假死、内存溢出问题排查】
  • shell-awk
  • TVS管用万用表测量方法详解(含二极管档使用指南)
  • 【微信小程序】webp资源上传失败
  • 告别碎片化!MCP 带来 AI Agent 开发生态的革命性突破
  • Qt之QMessageBox
  • 【RabbitMQ】实现RPC通信的完整指南
  • 浅谈算法中的贪心策略:从直觉到策略的思维跨越
  • ios打包ipa获取证书和打包创建经验分享
  • (独家)SAP CO模块中 销售发票对应的Cost Document中的PSG对象是什么东东??
  • leetcode0621. 任务调度器-medium
  • 论QT6多线程技术
  • linux-配置定时任务
  • 一道canvas算法题(看过记录下)
  • js在浏览器执行原理