STM32+ESP01S(WIFI)上传温湿度(DHT11)至巴法云+手机app

慈云数据 2024-05-14 技术支持 41 0

目录

  • 前言
    • 设计目标
    • 硬件介绍
    • 手机app
    • 软件设计
      • 连接ESP01S
      • 代码部分
        • 串口
          • Usart.h
          • Usart.c
          • Serial.h
          • Serial.c
          • ESP01S
            • ESP01S.h
            • ESP01S.c
            • 定时器
              • Timer.h
              • Timer.c
              • DHT11温湿度传感器
                • DHT11.h
                • DHT11.c
                • LED
                  • LED.h
                  • LED.c
                  • OLED
                  • 按键
                    • Key.h
                    • Key.c
                    • 主函数main
                    • App Inventor
                    • 结语

                      前言

                      翻东西时发现一个ESP01S模块,想着玩一下

                      本篇学习ESP01S连接巴法云,AT指令参考:https://espressif-docs.readthedocs-hosted.com/projects/esp-at/zh-cn/release-v2.2.0.0_esp8266/AT_Command_Set/index.html

                      设计目标

                      • STM32通过DHT11获取温湿度,通过ESP01S连接巴法云发布温湿度,手机app订阅巴法云获取温湿度
                      • STM32连接LED灯,实现通过手机app控制LED灯的状态

                        硬件介绍

                        • STM32F103C8T6最小系统板
                        • ESP01S模块
                        • DHT11温湿度传感器

                          手机app

                          手机app使用App Inventor平台开发,可视化编程,简单方便

                          软件设计

                          连接ESP01S

                          STM32通过USART2连接ESP01S

                          STM32ESP01S
                          PA2(TX)RX
                          PA3(RX)TX
                          VCCRST
                          VCCEN
                          3.33V3
                          GNDGND

                          注意:根据EPS01S规格书可查,3V3供电引脚需要外部供电电源输出电流在 500mA 以上,如果上电后不稳定(自动重启),可能是供电不足,单片机连接的电源电流有限,建议更换或增加电源(最小系统板尾部有USB-mrico连接手机充电器即可,建议先连接充电器再连接ST-LINK,防止电脑USB口电压不稳导致电脑出问题)

                          代码部分

                          串口

                          USART1连接电脑(使用串口工具)用于调试显示,USART2连接ESP01S

                          USART使用两组中断,接收中断和空闲中断实现“接收”和“接收完成”的功能

                          数组接收串口数据,初始化时把外部指针指向数组的地址,获取接收数据标志位时,直接对外部指针进行处理即可(不通过extern使用全局变量,便于移植),不需要调用函数传出接收数据(第二次接收数据时直接覆盖,因此需要及时处理)

                          Usart.h

                          #ifndef __USART_H
                          #define __USART_H
                          #include "stm32f10x.h"
                          #include 
                          #include 
                          #include 
                          #define USART_BUF_SIZE 100 /* USART一次收发数据长度 */
                          void Usart1_Init(unsigned int baud);                                      /* 串口1初始化 */
                          void Usart2_Init(unsigned int baud);                                      /* 串口2初始化 */
                          void Usart_SendString(USART_TypeDef *USARTx, uint8_t *str, uint16_t len); /* 串口数据发送 */
                          void UsartPrintf(USART_TypeDef *USARTx, char *fmt, ...);                  /* 串口格式化打印 */
                          void USART1_IRQHandler_Callback(uint8_t data, FlagStatus idle);           /* 串口1中断回调函数 */
                          void USART2_IRQHandler_Callback(uint8_t data, FlagStatus idle);           /* 串口2中断回调函数 */
                          #endif
                          

                          Usart.c

                          #include "Usart.h"
                          /*
                          ************************************************************
                          *	函数名称:	Usart1_Init
                          *	函数功能:	串口1初始化
                          *	入口参数:	baud:设定的波特率
                          *	返回参数:	无
                          *	说明:
                          ************************************************************
                          */
                          void Usart1_Init(unsigned int baud)
                          {
                              GPIO_InitTypeDef gpioInitStruct;
                              USART_InitTypeDef usartInitStruct;
                              NVIC_InitTypeDef nvicInitStruct;
                              //开启时钟
                              RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
                              RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
                              // PA9	TXD
                              gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
                              gpioInitStruct.GPIO_Pin = GPIO_Pin_9;
                              gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
                              GPIO_Init(GPIOA, &gpioInitStruct);
                              // PA10	RXD
                              gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                              gpioInitStruct.GPIO_Pin = GPIO_Pin_10;
                              gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
                              GPIO_Init(GPIOA, &gpioInitStruct);
                              //初始化USART1
                              usartInitStruct.USART_BaudRate = baud;
                              usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
                              usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                 // 接收和发送
                              usartInitStruct.USART_Parity = USART_Parity_No;                             // 无校验
                              usartInitStruct.USART_StopBits = USART_StopBits_1;                          // 1位停止位
                              usartInitStruct.USART_WordLength = USART_WordLength_8b;                     // 8位数据位
                              USART_Init(USART1, &usartInitStruct);
                              USART_Cmd(USART1, ENABLE);                     // 使能串口
                              USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 使能接收中断
                              USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); // 使能串口总线空闲中断
                              nvicInitStruct.NVIC_IRQChannel = USART1_IRQn;
                              nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
                              nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
                              nvicInitStruct.NVIC_IRQChannelSubPriority = 2;
                              NVIC_Init(&nvicInitStruct);
                          }
                          /*
                          ************************************************************
                          *	函数名称:	Usart2_Init
                          *	函数功能:	串口2初始化
                          *	入口参数:	baud:设定的波特率
                          *	返回参数:	无
                          *	说明:		TX-PA2		RX-PA3
                          ************************************************************
                          */
                          void Usart2_Init(unsigned int baud)
                          {
                              GPIO_InitTypeDef gpioInitStruct;
                              USART_InitTypeDef usartInitStruct;
                              NVIC_InitTypeDef nvicInitStruct;
                              RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
                              RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
                              // PA2	TXD
                              gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
                              gpioInitStruct.GPIO_Pin = GPIO_Pin_2;
                              gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
                              GPIO_Init(GPIOA, &gpioInitStruct);
                              // PA3	RXD
                              gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                              gpioInitStruct.GPIO_Pin = GPIO_Pin_3;
                              gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
                              GPIO_Init(GPIOA, &gpioInitStruct);
                              usartInitStruct.USART_BaudRate = baud;
                              usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件流控
                              usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                 // 接收和发送
                              usartInitStruct.USART_Parity = USART_Parity_No;                             // 无校验
                              usartInitStruct.USART_StopBits = USART_StopBits_1;                          // 1位停止位
                              usartInitStruct.USART_WordLength = USART_WordLength_8b;                     // 8位数据位
                              USART_Init(USART2, &usartInitStruct);
                              USART_Cmd(USART2, ENABLE);                     // 使能串口
                              USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 使能接收中断
                              USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); // 使能串口总线空闲中断
                              nvicInitStruct.NVIC_IRQChannel = USART2_IRQn;
                              nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
                              nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
                              nvicInitStruct.NVIC_IRQChannelSubPriority = 0;
                              NVIC_Init(&nvicInitStruct);
                          }
                          /*
                          ************************************************************
                          *	函数名称:	Usart_SendString
                          *	函数功能:	串口数据发送
                          *	入口参数:	USARTx:串口组
                          *				str:要发送的数据
                          *				len:数据长度
                          *	返回参数:	无
                          *	说明:
                          ************************************************************
                          */
                          void Usart_SendString(USART_TypeDef *USARTx, uint8_t *str, uint16_t len)
                          {
                              uint16_t count = 0;
                              for (; count  
                          

                          Serial.h

                          #ifndef __SERIAL_H
                          #define __SERIAL_H
                          #include "Usart.h"
                          #define SERIAL_USART USART1                                       /* 打印串口连接的串口 */
                          #define SERIAL_BUF_SIZE USART_BUF_SIZE                            /* 打印串口一次收发数据长度 */
                          #define SERIAL_USART_INIT(x) Usart1_Init(x)                       /* 打印串口连接串口初始化 */
                          #define Serial_Printf(...) UsartPrintf(SERIAL_USART, __VA_ARGS__) /* 打印串口发送数据 */
                          void Serial_Init(uint8_t **buf);  /* 打印串口初始化 */
                          FlagStatus Serial_Rec_Flag(void); /* 串口接收到数据标志位 */
                          #endif
                          

                          Serial.c

                          #include "Serial.h"
                          static FlagStatus Serial_Flag = RESET;      /* 接收到数据标志位 */
                          static uint8_t Serial_Buf[SERIAL_BUF_SIZE]; /* 接收到的数据数组 */
                          //==========================================================
                          //	函数名称:	Serial_Init
                          //	函数功能:	打印串口初始化
                          //	入口参数:	buf:存储获取数据的指针地址
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          void Serial_Init(uint8_t **buf)
                          {
                              SERIAL_USART_INIT(9600);
                              *buf = Serial_Buf;
                          }
                          //==========================================================
                          //	函数名称:	Serial_Rec_Flag
                          //	函数功能:	Serial接收到数据标志位
                          //	入口参数:	无
                          //	返回参数:	SET:接收完成    RESET:未完成接收
                          //	说明:
                          //==========================================================
                          FlagStatus Serial_Rec_Flag(void)
                          {
                              if (Serial_Flag == SET)
                              {
                                  Serial_Flag = RESET;
                                  return SET;
                              }
                              return RESET;
                          }
                          //==========================================================
                          //	函数名称:	USART1_IRQHandler_Callback
                          //	函数功能:	串口1中断回调函数
                          //	入口参数:	data:获取数据  idle:空闲,接收完成
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          void USART1_IRQHandler_Callback(uint8_t data, FlagStatus idle)
                          {
                              static uint8_t RxState = 0;       /* 状态变量 */
                              static uint8_t RxData_length = 0; /* 接收数据数量 */
                              if (idle == SET)
                              {
                                  RxState = 0;                      /* 状态置0 */
                                  Serial_Buf[RxData_length] = '\0'; /* 结尾 */
                                  Serial_Flag = SET;                /* 接收完成 */
                              }
                              else if (RxState == 0) /* 未接收 */
                              {
                                  RxState = 1;          /* 状态置1 */
                                  RxData_length = 0;    /* 接收数据数量清零 */
                                  Serial_Buf[0] = data; /* 获取接收数据 */
                                  RxData_length++;      /* 接收数据数量加1 */
                              }
                              else if (RxState == 1) /* 接收中 */
                              {
                                  Serial_Buf[RxData_length] = data;          /* 获取接收数据 */
                                  if (RxData_length  
                          

                          ESP01S

                          ESP01S通过WiFi连接巴法云

                          根据巴法云接入文档提示,可根据主题后三位判断主题类型,有主题类型的设备可以在巴法云手机app上直接查看和控制设备,如果不需要巴法云手机app可不需要加后三位数字

                          ESP01S.h

                          #ifndef _ESP01S_H
                          #define _ESP01S_H
                          #include 
                          #include "Usart.h"
                          #include "Serial.h"
                          #include "Delay.h"
                          #define ESP01S_USART USART2                                           /* ESP01S连接的串口 */
                          #define ESP01S_BUF_SIZE USART_BUF_SIZE                                /* ESP01S一次收发数据长度 */
                          #define ESP01S_USART_INIT(x) Usart2_Init(x)                           /* ESP01S连接串口初始化 */
                          #define ESP01S_Printf(...) UsartPrintf(ESP01S_USART, __VA_ARGS__)     /* ESP01S发送数据 */
                          #define ESP01S_MQTT_INFO "AT+CIPSTART=\"TCP\",\"bemfa.com\",8344\r\n" /* 连接巴法云的AT指令 */
                          #define MQTT_PING_CMD "cmd=0&msg=ping\r\n"                            /* 心跳命令 */
                          #define MQTT_PING_REC "cmd=0&res=1"                                   /* 心跳返回信息 */
                          #define MQTT_PING_TIME_MAX 30                                         /* MQTT心跳最长时间(秒) */
                          extern char ESP01S_MQTT_TOPIC_LED[]; /* 连接巴法云的主题LED */
                          typedef enum
                          {
                              MQTT_Cmd_Add = 1,       /* 添加订阅 */
                              MQTT_Cmd_Send = 2,      /* 发布 */
                              MQTT_Cmd_AddAndRec = 3, /* 订阅并获取一次历史信息 */
                              MQTT_Cmd_RecTime = 7,   /* 获取时间 */
                              MQTT_Cmd_RecSend = 9,   /* 获取一次已发消息 */
                          } _MQTT_Cmd;                /* MQTT命令 */
                          void ESP01S_Init(uint8_t **buf);           /* 初始化ESP01S */
                          FlagStatus ESP01S_Rec_Flag(void);          /* ESP01S接收到数据标志位 */
                          void ESP01S_ALL(void);                     /* ESP01S循环执行部分 */
                          void ESP01S_Loop_1s(void);                 /* ESP01S定时执行部分 */
                          void MQTT_Set_LED(FunctionalState state, uint8_t num);                                    /* LED控制 */
                          void MQTT_Send_humi_temp(uint8_t humi, uint8_t humi_dec, uint8_t temp, uint8_t temp_dec); /* 发送温湿度 */
                          void ESP01S_On_Line_Feedback(void);        /* ESP01S在线反馈 */
                          void ESP01S_Send_String(uint8_t *string);  /* 发送数据到ESP01S */
                          #endif
                          

                          ESP01S.c

                          #include "ESP01S.h"
                          static char ESP01S_MQTT_UID[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; /* 连接巴法云的秘钥 */
                          char ESP01S_MQTT_TOPIC_LED[] = "led002";                            /* 连接巴法云的主题LED */
                          char ESP01S_MQTT_TOPIC_HUMI[] = "humi004";                          /* 连接巴法云的主题湿度 */
                          char ESP01S_MQTT_TOPIC_TEMP[] = "temp004";                          /* 连接巴法云的主题温度 */
                          static char ESP01S_WIFI_SSID[] = "xxxxxxx";      /* 连接wifi的名称 */
                          static char ESP01S_WIFI_PASSWORD[] = "xxxxxxxx"; /* 连接wifi的密码 */
                          static uint8_t ESP01S_buf[ESP01S_BUF_SIZE];    /* 接收ESP-01s的返回数据数组 */
                          static FlagStatus ESP01S_buf_continue = RESET; /* 是否允许接收多组数据 */
                          static FlagStatus Recive_end_Flag = RESET;     /* ESP01S数据接收完成标志位 */
                          static FlagStatus Recive_Busy = RESET;         /* ESP01S数据接收中标志位 */
                          static FlagStatus MQTT_On_Line_Flag = RESET;   /* MQTT在线标志位 */
                          static FlagStatus MQTT_Ping_Flag = RESET;      /* MQTT发送心跳标志位 */
                          static uint8_t MQTT_Ping_Time_s = 0;           /* MQTT心跳时间(s) */
                          static uint16_t RxData_length = 0;             /* 接收数据长度 */
                          //==========================================================
                          //	函数名称:	ESP01S_Recive_Clean
                          //	函数功能:	接收信息清除
                          //	入口参数:	无
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          static void ESP01S_Recive_Clean(void)
                          {
                              RxData_length = 0;       /* 接收数据数量清零 */
                              ESP01S_buf[0] = '\0';    /* 清除接收数据 */
                              Recive_Busy = RESET;     /* 清除数据接收中标志位 */
                              Recive_end_Flag = RESET; /* 清除ESP01S接收数据标志位 */
                          }
                          //==========================================================
                          //	函数名称:	ESP01S_SendCmd_Printf
                          //	函数功能:	发送命令
                          //	入口参数:	cmd:命令
                          //			   fmt:输入信息
                          //	返回参数:	SET-成功	RESET-失败
                          //	说明:
                          //==========================================================
                          static FlagStatus ESP01S_SendCmd_Printf(char *res, char *fmt, ...)
                          {
                              char String[ESP01S_BUF_SIZE]; /* 接收输入变量数组,如果数组不够大,可以修改一下 */
                              uint8_t times = 20;           /* 检查返回数据次数 */
                              va_list arg;
                              va_start(arg, fmt);
                              vsprintf(String, fmt, arg);
                              ESP01S_buf_continue = SET; /* 允许接收多组数据 */
                              do
                              {
                                  while (Recive_Busy == SET) /* 等待串口空闲 */
                                  {
                                      Delay_ms(1);
                                  }
                                  ESP01S_Recive_Clean(); /* 接收信息清零 */
                                  ESP01S_Printf(String); /* 发送命令 */
                                  Delay_ms(5);
                              } while ((strstr((const char *)ESP01S_buf, "busy s...") != NULL) || (strstr((const char *)ESP01S_buf, "busy p...") != NULL)); /* 输入正常 */
                              while (times--)
                              {
                                  while (Recive_Busy == SET) /* 等待接收完成 */
                                  {
                                      Delay_ms(1);
                                  }
                                  if (strstr((const char *)ESP01S_buf, res) != NULL) /* 如果检索到关键词 */
                                  {
                                      ESP01S_buf_continue = RESET; /* 禁止接收多组数据 */
                                      Recive_end_Flag = RESET;     /* 清除ESP01S接收数据标志位 */
                                      return SET;
                                  }
                                  Delay_ms(10);
                              }
                              Recive_end_Flag = RESET;     /* 清除ESP01S接收数据标志位 */
                              ESP01S_buf_continue = RESET; /* 禁止接收多组数据 */
                              return RESET;
                          }
                          //==========================================================
                          //	函数名称:	ESP01S_EXIT_CIPMODE
                          //	函数功能:	ESP01S退出穿透模式
                          //	入口参数:	无
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          static void ESP01S_EXIT_CIPMODE(void)
                          {
                              if (ESP01S_SendCmd_Printf("OK", "AT\r\n") == SET)
                                  return;
                              Serial_Printf("退出透传模式\r\n");
                              Delay_ms(40);
                              while (Recive_Busy == SET)
                                  ;                 /* 等待串口空闲 */
                              ESP01S_Printf("+++"); /* 退出透传发送 */
                              Delay_ms(40);
                              ESP01S_SendCmd_Printf("OK", "AT+CIPMODE=0\r\n"); /* 退出透传模式 */
                              ESP01S_SendCmd_Printf("OK", "AT+CIPCLOSE\r\n");  /* 断开连接 */
                          }
                          //==========================================================
                          //	函数名称:	ESP01S_Status
                          //	函数功能:	ESP01S状态
                          //	入口参数:	无
                          //	返回参数:	状态
                          //	说明:   0: ESP station 为未初始化状态
                          //          1: ESP station 为已初始化状态,但还未开始 Wi-Fi 连接
                          //          2: ESP station 已连接 AP,获得 IP 地址
                          //          3: ESP station 已建立 TCP、UDP 或 SSL 传输
                          //          4: ESP 设备所有的 TCP、UDP 和 SSL 均断开
                          //          5: ESP station 开始过 Wi-Fi 连接,但尚未连接上 AP 或从 AP 断开
                          //==========================================================
                          static uint8_t ESP01S_Status(void)
                          {
                              uint8_t status = 0;
                              ESP01S_EXIT_CIPMODE(); /* 退出透传模式 */
                              if (ESP01S_SendCmd_Printf("OK", "AT+CIPSTATUS\r\n") == SET) /* 查询连接状态和信息 */
                              {
                                  status = atoi(strstr((char *)ESP01S_buf, "STATUS:") + strlen("STATUS:")); /* 获取STATUS:后一位数字 */
                                  Serial_Printf("ESP01S连接模式为:%d\r\n", status);                        /* 串口打印 */
                              }
                              return status;
                          }
                          //==========================================================
                          //	函数名称:	MQTT_SendCmd
                          //	函数功能:	MQTT发送命令
                          //	入口参数:	cmd:命令
                          //             topic:主题
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          static void MQTT_SendCmd(_MQTT_Cmd cmd, char *topic)
                          {
                              ESP01S_SendCmd_Printf("cmd", "cmd=%d&uid=%s&topic=%s\r\n", cmd, ESP01S_MQTT_UID, topic);
                          }
                          //==========================================================
                          //	函数名称:	WIFI_Connect
                          //	函数功能:	WIFI设置
                          //	入口参数:	ssid:WIFI名称
                          //	           pwd:WIFI密码
                          //	返回参数:	是否连接成功
                          //	说明:
                          //==========================================================
                          static FlagStatus WIFI_Connect(char *ssid, char *pwd)
                          {
                              Serial_Printf("\r\nWIFI连接\r\n");       /* 串口打印 */
                              if (ESP01S_SendCmd_Printf("OK", "AT+CWMODE=1\r\n") == SET)                              /* 1 station模式 2 AP路由器模式 3 station+AP混合模式 */
                                  return ESP01S_SendCmd_Printf("CONNECTED", "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd); /* 连接WIFI */
                              return RESET;
                          }
                          //==========================================================
                          //	函数名称:	MQTT_Connect
                          //	函数功能:	连接MQTT
                          //	入口参数:	是否连接成功
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          static FlagStatus MQTT_Connect(void)
                          {
                              Serial_Printf("MQTT连接\r\n");                              /* 串口打印 */
                              if (ESP01S_SendCmd_Printf("OK", "AT+CIPMODE=1\r\n") == SET) /* 设置为透传模式 */
                              {
                                  if (ESP01S_SendCmd_Printf("OK", ESP01S_MQTT_INFO) == SET) /* 连接到MQTT服务器 */
                                  {
                                      if ((ESP01S_SendCmd_Printf(">", "AT+CIPSEND\r\n")) == SET) /* 进入透传模式,下面发的都会无条件传输 */
                                      {
                                          Delay_ms(200);
                                          MQTT_SendCmd(MQTT_Cmd_Add, ESP01S_MQTT_TOPIC_LED);                       /* 订阅主题 */
                                          MQTT_SendCmd(MQTT_Cmd_Add, ESP01S_MQTT_TOPIC_HUMI);                      /* 订阅主题 */
                                          MQTT_SendCmd(MQTT_Cmd_Add, ESP01S_MQTT_TOPIC_TEMP);                      /* 订阅主题 */
                                          MQTT_On_Line_Flag = ESP01S_SendCmd_Printf(MQTT_PING_REC, MQTT_PING_CMD); /* 发送MATT心跳,判断是否连接 */
                                          if (MQTT_On_Line_Flag == SET)
                                              Serial_Printf("MQTT订阅成功\r\n"); /* 串口打印 */
                                          return MQTT_On_Line_Flag;
                                      }
                                  }
                              }
                              return RESET;
                          }
                          //==========================================================
                          //	函数名称:	ESP01S_Init
                          //	函数功能:	初始化ESP01S
                          //	入口参数:	buf:存储获取数据的指针地址
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          void ESP01S_Init(uint8_t **buf)
                          {
                              uint8_t status; /* ESP01S连接状态 */
                              ESP01S_USART_INIT(115200);             /* ESP01S连接串口初始化 */
                              *buf = ESP01S_buf;                     /* 传递参数 */
                              Serial_Printf("\r\nESP01S初始化\r\n"); /* 串口打印 */
                              Delay_ms(10);
                              MQTT_On_Line_Flag = ESP01S_SendCmd_Printf(MQTT_PING_REC, MQTT_PING_CMD); /* 心跳连接,cpu重启,ESP01S保持上电 */
                              if (MQTT_On_Line_Flag == SET)
                              {
                                  MQTT_SendCmd(MQTT_Cmd_Add, ESP01S_MQTT_TOPIC_LED);  /* 订阅主题 */
                                  MQTT_SendCmd(MQTT_Cmd_Add, ESP01S_MQTT_TOPIC_HUMI); /* 订阅主题 */
                                  MQTT_SendCmd(MQTT_Cmd_Add, ESP01S_MQTT_TOPIC_TEMP); /* 订阅主题 */
                                  Serial_Printf("\r\nMQTT在线\r\n");                  /* 串口打印 */
                                  return;
                              }
                              status = ESP01S_Status();       /* 获取ESP01S连接状态 */
                              if (status == 1 || status == 5) /* 未连接或连接后断开 */
                              {
                                  WIFI_Connect(ESP01S_WIFI_SSID, ESP01S_WIFI_PASSWORD); /* 连接FIWI */
                                  MQTT_Connect();                                       /* 连接MQTT */
                              }
                              else
                                  MQTT_Connect(); /* 连接MQTT */
                          }
                          //==========================================================
                          //	函数名称:	ESP01S_On_Line_Feedback
                          //	函数功能:	ESP01S在线反馈
                          //	入口参数:	无
                          //	返回参数:	无
                          //	说明:100ms执行一次
                          //==========================================================
                          void ESP01S_On_Line_Feedback(void)
                          {
                              MQTT_Ping_Time_s = 0;    /* 心跳时间清理 */
                              MQTT_On_Line_Flag = SET; /* MQTT在线 */
                          }
                          //==========================================================
                          //	函数名称:	ESP01S_ALL
                          //	函数功能:	ESP01S循环执行部分
                          //	入口参数:	无
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          void ESP01S_ALL(void)
                          {
                              uint8_t status; /* ESP01S连接状态 */
                              if (MQTT_Ping_Flag == SET) /* MQTT发送心跳标志位 */
                              {
                                  MQTT_On_Line_Flag = ESP01S_SendCmd_Printf(MQTT_PING_REC, MQTT_PING_CMD); /* 发送MATT心跳,判断是否连接 */
                                  if (MQTT_On_Line_Flag == RESET)
                                  {
                                      Serial_Printf("MQTT离线\r\n"); /* 串口打印 */
                                  }
                                  MQTT_Ping_Flag = RESET; /* 清除标志位 */
                              }
                              if (MQTT_On_Line_Flag == RESET) /* MQTT不在线 */
                              {
                                  status = ESP01S_Status();                      /* 获取ESP01S连接状态 */
                                  if (status == 0 || status == 1 || status == 5) /* 未连接或连接后断开 */
                                  {
                                      WIFI_Connect(ESP01S_WIFI_SSID, ESP01S_WIFI_PASSWORD); /* 连接FIWI */
                                      MQTT_Connect();                                       /* 连接MQTT */
                                  }
                                  else
                                      MQTT_Connect(); /* 连接MQTT */
                              }
                          }
                          //==========================================================
                          //	函数名称:	ESP01S_Loop_1s
                          //	函数功能:	ESP01S定时执行部分
                          //	入口参数:	无
                          //	返回参数:	无
                          //	说明:1s执行一次
                          //==========================================================
                          void ESP01S_Loop_1s(void)
                          {
                              MQTT_Ping_Time_s++;
                              if (MQTT_Ping_Time_s >= MQTT_PING_TIME_MAX) /* 心跳 */
                              {
                                  MQTT_Ping_Flag = SET; /* MQTT心跳 */
                                  MQTT_Ping_Time_s = 0;
                              }
                          }
                          //==========================================================
                          //	函数名称:	USART2_IRQHandler_Callback
                          //	函数功能:	串口2中断回调函数
                          //	入口参数:	data:获取数据  idle:空闲,接收完成
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          void USART2_IRQHandler_Callback(uint8_t data, FlagStatus idle)
                          {
                              Recive_Busy = SET;          /* 数据接收中标志位 */
                              static uint8_t RxState = 0; /* 接收状态 */
                              if (idle == SET) /* 接收完成 */
                              {
                                  RxState = 0;                          /* 状态置0 */
                                  Recive_end_Flag = SET;                /* 接收完成 */
                                  Recive_Busy = RESET;                  /* 清除数据接收中标志位 */
                                  if (ESP01S_buf_continue == RESET)     /* 禁止接收多组数据状态下,接收完成后加'\0'结尾 */
                                      ESP01S_buf[RxData_length] = '\0'; /* 结尾 */
                              }
                              else if (RxState == 0) /* 未接收 */
                              {
                                  Recive_end_Flag = RESET; /* 未接收 */
                                  RxState = 1;             /* 状态置1 */
                                  if (ESP01S_buf_continue == RESET)          /* 禁止接收多组数据状态下,接收第一个data时,RxData_length置0 */
                                      RxData_length = 0;                     /* 接收数据数量清零 */
                                  ESP01S_buf[RxData_length] = data;          /* 获取接收数据 */
                                  if (RxData_length  
                          

                          上文中xxxxx的部分替换成自己的数据

                          ESP01S_Send_String函数可用于前期对ESP01S进行测试,也可直接使用ESP01S直接转接电脑的方式进行测试,但是需要多接几次线,嫌麻烦没试,该函数还可用于后期功能拓展(如:更换wifi、更换巴法云秘钥或主题,连接上位机进行控制显示等)

                          定时器

                          为了保障连接稳定,需要定时发送心跳信号,所以还需要一个定时器

                          Timer.h

                          #ifndef __TIMER_H
                          #define __TIMER_H
                          #include "stm32f10x.h"
                          void Timer2_Init(void);          /* 定时器2初始化 */
                          void TIM2_IRQHandler_Loop(void); /* 定时器2中断回调函数,中断间隔1ms */
                          #endif
                          

                          Timer.c

                          #include "Timer.h"
                          //==========================================================
                          //	函数名称:	Timer2_Init
                          //	函数功能:	初始化定时器2
                          //	入口参数:	无
                          //	返回参数:	无
                          //	说明:      设定为1ms中断1次
                          //==========================================================
                          void Timer2_Init(void)
                          {
                              // 开启时钟
                              RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
                              // 选择时基单元的时钟
                              TIM_InternalClockConfig(TIM2);
                              // 配置时基单元
                              TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
                              TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
                              TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
                              TIM_TimeBaseInitStruct.TIM_Period = 1000 - 1;
                              TIM_TimeBaseInitStruct.TIM_Prescaler = SystemCoreClock / 1000 / 1000 - 1;
                              TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
                              TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
                              // 清除TIM2的挂起标志
                              TIM_ClearFlag(TIM2, TIM_FLAG_Update);
                              // 使能中断
                              TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
                              // 配置NVIC
                              // 优先级分组
                              NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
                              // NVIC初始化
                              NVIC_InitTypeDef NVIC_InitStruct;
                              NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
                              NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
                              NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
                              NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
                              NVIC_Init(&NVIC_InitStruct);
                              // 启动定时器
                              TIM_Cmd(TIM2, ENABLE);
                          }
                          //==========================================================
                          //	函数名称:	TIM2_IRQHandler
                          //	函数功能:	定时器2中断函数,中断间隔1ms
                          //	入口参数:	无
                          //	返回参数:	无
                          //	说明:
                          //==========================================================
                          void TIM2_IRQHandler(void)
                          {
                              if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) /* 判断中断标志位 */
                              {
                                  TIM2_IRQHandler_Loop();                     /* 中断回调函数,中断间隔1ms */
                                  TIM_ClearITPendingBit(TIM2, TIM_IT_Update); /* 清除标志位 */
                              }
                          }
                          

                          DHT11温湿度传感器

                          DHT11网上资料很多,就不解释了

                          DHT11.h

                          #ifndef __DHT11_H
                          #define __DHT11_H
                          #include "stm32f10x.h"
                          #include "Delay.h"
                          #define DHT11_DATA_IN GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) /* 获取STH11数据引脚状态 */
                          #define DHT11_DATA_OUT_H GPIO_SetBits(GPIOB, GPIO_Pin_14)       /* 置STH11数据引脚为高电平 */
                          #define DHT11_DATA_OUT_L GPIO_ResetBits(GPIOB, GPIO_Pin_14)     /* 置STH11数据引脚为低电平 */
                          void DHT11_Init(void);             /* DHT11初始化 */
                          uint8_t DHT11_Read(uint8_t *data); /* 获取DHT11数据 */
                          #endif
                          

                          DHT11.c

                          #include "DHT11.h"
                          /*********************************************************
                          函数名称:DHT11_Init
                          函数功能:初始化DHT11
                          入口参数:无
                          返回结果:无
                          函数说明:
                          **********************************************************/
                          void DHT11_Init(void)
                          {
                              RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /* 开启GPIOB外设时钟 */
                          }
                          /*********************************************************
                          函数名称:DHT11_GPIO_OUT
                          函数功能:初始化数据引脚为输出
                          入口参数:无
                          返回结果:无
                          函数说明:
                          **********************************************************/
                          static void DHT11_GPIO_OUT(void)
                          {
                              GPIO_InitTypeDef GPIO_InitStructure;
                              GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
                              GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
                              GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                              GPIO_Init(GPIOB, &GPIO_InitStructure);
                          }
                          /*********************************************************
                          函数名称:DHT11_GPIO_IN
                          函数功能:初始化数据引脚为输入
                          入口参数:无
                          返回结果:无
                          函数说明:
                          **********************************************************/
                          static void DHT11_GPIO_IN(void)
                          {
                              GPIO_InitTypeDef GPIO_InitStructure;
                              GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
                              GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                              GPIO_Init(GPIOB, &GPIO_InitStructure);
                          }
                          /*********************************************************
                          函数名称:DHT11_Start
                          函数功能:开启
                          入口参数:无
                          返回结果:无
                          函数说明:
                          **********************************************************/
                          static void DHT11_Start(void)
                          {
                              DHT11_GPIO_OUT(); /* 输出模式 */
                              DHT11_DATA_OUT_H; /* 拉高 */
                              Delay_us(2);      /* 2us */
                              DHT11_DATA_OUT_L; /* 拉低 */
                              Delay_ms(20);     /* 至少18ms */
                              DHT11_DATA_OUT_H; /* 拉高 */
                              Delay_us(30);     /* 20-40us */
                              DHT11_GPIO_IN();  /* 输入模式 */
                          }
                          /*********************************************************
                          函数名称:DHT11_Ask
                          函数功能:应答
                          入口参数:无
                          返回结果:1:成功       0:失败
                          函数说明:开始信号结束,DHT11发送80us低电平响应信号,发送响应信号后,再把总线拉高80us
                          **********************************************************/
                          static uint8_t DHT11_Ask(void)
                          {
                              uint8_t retry = 0;
                              if (DHT11_DATA_IN == 0)
                              {
                                  while (DHT11_DATA_IN == 0 && retry = 100) //超过100us退出,以免卡死
                                          return 0;
                                  }
                                  retry = 0;
                                  while (DHT11_DATA_IN == 1 && retry = 100) //超过100us退出,以免卡死
                                          return 0;
                                  }
                              }
                              return 1;
                          }
                          /*********************************************************
                          函数名称:DHT11_Read_Byte
                          函数功能:读一个字节
                          入口参数:无
                          返回结果:获取的字节
                          函数说明:
                          **********************************************************/
                          static uint8_t DHT11_Read_Byte(void)
                          {
                              uint8_t i, retry;
                              uint8_t data = 0;
                              for (i = 0; i 
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon