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

发布于:2025-05-17 ⋅ 阅读:(16) ⋅ 点赞:(0)

飞书文档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 256

uint8_t rx_buf[BUFFER_SIZE];  //应用处理buffer
bool rx_status = false;
extern DMA_HandleTypeDef hdma_uart4_rx;
uint8_t dma_rxbuf[BUFFER_SIZE];                                       //DMA接收buffer

static 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 256

uint8_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接收buffer

static 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 阿里云


网站公告

今日签到

点亮在社区的每一天
去签到