STM32实战——ESP8266 WIFI模块

ESP8266

硬件介绍

ESP8266系列模组有哪些:

在本实验中,ESP8266ESP-01不做区分。

ESP-01引脚介绍:

引脚 功能
3.3 3.3V供电,避免使用5V供电
RX UART_RXD,异步串口接受端
RST 外部复位引脚,低电平有效,默认高电平
IO0 GPIO_0引脚:状态:1.悬空:Flash下载模式和工作模式:2.下拉:串口下载模式
EN 使能端口,高电平工作,低电平模块不工作
IO2 GPIO_2引脚,开机上电时禁止下拉,默认高电平
TX UART_TXD,异步串口发送端
GND GND接地引脚

实物图如下(某些板子没有丝印端口说明,可以参照下图):

引脚连接如下:

引脚 连接
3.3V 3.3V
RST 3.3V
EN 3.3V
IO2 3.3V
GND GND
IO0 GND
TXD RXD
RXD TXD

硬件连接图(2)

使用ESP串口工具

某宝上有现成的调试ESP8266模块的串口工具,已将各个引脚接好,还带有RST按键,烧录固件库或者调试程序使用很方便。

本次实验测试时使用该串口工具。

三种模式

ESP8266 支持 softAP 模式,station 模式,softAP + station 共存模式三种。

利用 ESP8266 可以实现十分灵活的组网方式和网络拓扑。

提示

SoftAP:即无线接入点,是一个无线网络的中心节点。通常使用的无线路由器就是一个无线接入点。

Station:即无线终端,是一个无线网络的终端端。

AT命令

此外,在AT+CIPSEND输入模式下发送+++(不需要换行),即可退出输入模式。

ATE1开启回显,ATE0关闭回显。

AT+CIOBAUD=115200将波特率修改为115200。

ESP8266 TCP通信测试

网络环境准备

手机开启流量,开启热点,设置热点名称(最好是6位字母以下)和密码。

将电脑连接到手机热点。

电脑端准备

1、网络调试

win+R 输入cmd进入DOS窗口,之后输入ipconfig查看当前电脑IP地址,例如我的IP为192.168.41.242

打开网络调试工具(任意工具即可,例如野火网络调试助手),将电脑配置为TCP Server,输入刚刚的IP192.168.41.242,端口号自己决定(需要与下一步相匹配),例如8080。

点击开始监听。

2、串口

将"ESP8266模块的串口工具"插入电脑USB口,打开串口调试工具(任意串口调试工具均可),设置波特率115200(ESP8266默认波特率),数据位8位,停止位1位,校验位无。

接收与发送均为"文本模式",编码为GBK编码。

ESP8266连接流程

依次利用串口向ESP8266输入以下命令。

  • AT\r\n
    检查ESP8266模块连接是否正常
  • AT+CWMODE=1\r\n
    配置模块为Sta模式
  • AT+CWJAP="WIFI名称","WIFI密码"\r\n
    连接指定WIFI,确保为自己的WIFI
  • AT+CIPMUX=0\r\n
    设置成单连接
  • AT+CIPSTART="TCP","192.168.41.242",8080\r\n
    创建TCP连接,IP地址为电脑的IP,串口为电脑监听的端口号
  • AT+CIPMODE=1\r\n
    进入透传模式,进入到透传模式后AT指令就会失效,需要退出后才能生效
  • AT+CIPSEND\r\n
    准备向服务器发送请求,前面都成功的前提下发送完这个指令后会出现一个>,此时输入发送信息即可

如果前面的命令均正确,则发送Hello后,此时电脑网络调试工具会接收Hello

电脑网络调试工具发送123,ESP8266也会收到123

至此,单独对ESP8266的设置和测试完成。接下来可以编写STM32代码。

附:完整的输入输出信息(\r\n表示按一次回车)

输入:

txt 复制代码
AT\r\n
ATE0\r\n
AT+CWMODE=1\r\n
AT+CWJAP="bwifyt","123456789"\r\n
AT+CIPMUX=0\r\n
AT+CIPSTART="TCP","192.168.41.242",8080\r\n
AT+CIPMODE=1\r\n
AT+CIPSEND\r\n

输出:

txt 复制代码
AT


OK
ATE0


OK

OK
WIFI CONNECTED
WIFI GOT IP

OK

OK

ERROR
CLOSED

ERROR
CLOSED

ERROR
CLOSED
CONNECT

OK

OK

OK

>

ESP8266 HTTP测试

HTTP协议

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。

HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。

ESP8266发送HTTP请求

这里使用心知天气进行测试。

服务器的IP地址可以使用ping api.seniverse.com命令获得。

端口号一般为80端口,如果是其他端口,请先使用网络调试助手确保可行。

使用正确的AT命令,重新设置ESP8266连接的IP地址(或者重启模块,重新设置,参照上一小节内容)。

发送格式

txt 复制代码
GET /v3/weather/now.json?key=你的密钥&location=beijing&language=zh-Hans&unit=c

响应:服务器返回的数据

txt 复制代码
{"results":[{"location":{"id":"WX4FBXXFKE4F","name":"北京","country":"CN","path":"北京,北京,中国","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"now":{"text":"多云","code":"4","temperature":"16"},"last_update":"2024-03-31T20:24:29+08:00"}]}

也可以使用完整的GET请求:

txt 复制代码
GET /v3/weather/now.json?key=你的密钥&location=beijing&language=zh-Hans&unit=c HTTP/1.1
Content-Type: application/json;charset=utf-8
Host: www.liefyuan.top
Connection: Keep Alive

注意

GET之后有一空格,HTTP/1.1之前有一空格。最后需要以两行换行表示结束。
响应信息

发送完整的GET请求,可以得到完整的响应信息

使用简略的GET请求,可以得到简略的响应信息

至于POST请求,需要与后端进行沟通,才能够确定具体的发送格式。

ESP8266接收响应

提示

以下内容与我目前所做的项目高度相关,因此有部分其他代码不做解释,只讲解关键点代码

发送HTTP请求之后,需要接收相关的响应,并对数据进行解析。

C语言有类似于CJSON的库可以能够实现数据解析做这件事,但是我们这里依旧采用自编代码实现。

优点是不需要导入CJSON的代码,对于单片机要求不高。缺点是需要手动编写,但是我们请求的次数不多,也就显得不是很麻烦了。

1、初始化

首先进行初始化,开启串口接收数据的中断。

C 复制代码
// USART相关配置

/*中断输出配置*/
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 开启串口接收数据的中断
USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); // 开启串口接收数据的中断

// NVIC相关配置

这里的"两个"中断都需要打开,不然无法正常接收到数据。

2、中断函数

之后编写我们需要的中断函数,即将ESP8266接收到的数据保存下来。

c 复制代码
/**
 * @brief  串口3接收到数据中断回调函数
 * @param  None
 * @retval None
 */
static void ESP8266_FrameFinish_CallBack(void) {
  Serial_Printf("\r\n中断回调函数串口输出:\r\n%s", ESP8266_Buffer.Body);
}

/**
 * @brief  串口3中断函数
 * @param  None
 * @retval None
 */
void USART3_IRQHandler(void) {
  if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
  {
    // 当接收没有结束时,将源源不断的接收到的字符存入缓冲区
    if (ESP8266_Buffer.Length < (USART_RX_BUF_SIZE - 1))
    {
      ESP8266_Buffer.Body[ESP8266_Buffer.Length++] = (char)USART_ReceiveData(USART3);
    }
  }
  if (USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)
  {
    // 当接收结束时,向缓冲区尾端添加结束符
    ESP8266_Buffer.FinishFlag = 1;
    ESP8266_Buffer.Body[ESP8266_Buffer.Length] = '\0';
    // 清除串口空闲中断标志位
    volatile uint16_t temp;
    temp = USART3->SR;
    temp = USART3->DR;
    ESP8266_FrameFinish_CallBack();
  }
}

3、发送HTTP接收数据

c 复制代码
/**
 * @brief  清空ESP8266_Buffer结构体
 * @param  None
 * @retval None
 */
void ESP8266_ClearBuffer(void)
{
  memset(ESP8266_Buffer.Body, 0, USART_RX_BUF_SIZE);  // 清空缓存区数据
  ESP8266_Buffer.FinishFlag = 0;  // 清空FinishFlag, 表示没有接收完成
  ESP8266_Buffer.Length = 0;      // 清空Length, 表示接收长度为0
}

/**
 * @brief  HTTP GET类型请求
 * @param  address 请求地址
 * @param  timeout 超时时间(单位:100ms)
 * @retval char* 字符数组
 */
char* ESP8266_HTTP_Get(char* address, uint8_t timeout)
{
  ESP8266_ClearBuffer();  // 清空ESP8266缓存
  ESP8266_Printf("GET %s HTTP/1.1\r\n\r\n", address);
  while(timeout--)
  {
    Delay_ms(100);
    if(ESP8266_Buffer.FinishFlag)
    {
      return ESP8266_GetBuffer();
    }
  }
  
  return "HTTP Send Failed.";
}

4、解析数据

由于我的接收响应是这样的

json 复制代码
{
    "status": "1",
    "msg": [
        {
            "id": 7,
            "name": "temperature",
            "value": "26.0"
        },
        {
            "id": 8,
            "name": "humidity",
            "value": "100.0"
        },
        {
            "id": 9,
            "name": "concentration",
            "value": "200.9"
        }
    ]
}

所以我的解析数据函数如下(添加了注释,相信大家能够明白)

c 复制代码
/**
 * @brief  从res中提取信息, 数据类型为uint8_t
 * @param  res: 响应字符串
 * @param  name: 数据名称
              temperature: 温度
              humidity: 湿度
              concentration: 浓度
 * @param  integer_part: 整数部分
 * @param  decimal_part: 小数部分
 * @retval 无
 */
void GetInformation(char *res, char *name, uint8_t *integer_part, uint8_t *decimal_part) {
	char *key_start = strstr(res, name);              // 寻找name开头
	char *result_start = strstr(key_start, "value") + 9;  // 寻找数据开头
	char *dot = strchr(result_start, '.');                // 寻找小数点
	char *result_end = strchr(result_start, '\"');    // 寻找数据结尾
  
	char string_integer_part[5];
	char string_decimal_part[5];
	strncpy(string_integer_part, result_start, dot - result_start); // 整数部分字符串
	strncpy(string_decimal_part, dot + 1, result_end - dot - 1);    // 小数部分字符串

	*integer_part = atoi(string_integer_part);      // 整数部分
	*decimal_part = atoi(string_decimal_part);      // 小数部分
}

5、示例代码

c 复制代码
// ESP8266_HTTP_Get是请求HTTP的参数,将返回一个字符串指针
char* res = ESP8266_HTTP_Get("/your_site", 100);
char* res_end;
do
{
	res = ESP8266_GetBuffer();
	res_end = strstr(res, "}]}");
	Delay_ms(100);
}while(res_end == NULL);

// 获取温度, 湿度, PM2.5浓度值
char* name = "temperature";
GetInformation(res, name, &temp.Temp_H_Threshold, &temp.Temp_L_Threshold);

参考链接

STM32外设系列---ESP8266(WIFI)_stm32 esp8266-CSDN博客

esp8266学习记录_stm32+esp8266测试方法-CSDN博客

STM32-连接wifi模块(esp8266)_stm32wifi模块-CSDN博客

ESP8266-01引脚说明与连接_esp01引脚定义-CSDN博客

HTTP 消息结构 | 菜鸟教程

ESP8266------AT指令发送POST请求

ESP8266使用AT指令发送GET方式HTTP请求

相关推荐
十月的皮皮9 小时前
stm20260720-从新手 C 到量产 STM32 工程:程序设计推导指南
c语言·开发语言·stm32·stm32cubemx·hal库
开发笔记-阿牛9 小时前
解析一款有意思的产品||CK6159A语音芯片设计的儿童专注力训练机-舒尔特玩具
stm32·单片机·嵌入式硬件·音频
搞全栈小苏11 小时前
SIMetrix_simplis8.4安装教程——附安装包
stm32·单片机·嵌入式硬件·电力电子
qq_5739678212 小时前
STM32控制器
stm32·单片机·嵌入式硬件
某林21213 小时前
履带小车底盘stm32F103RCT6开发
人工智能·stm32·单片机·嵌入式硬件·架构·人机交互·ros2
做萤石二次开发的哈哈15 小时前
萤石 ERTC Windows SDK 包含哪些类型定义?
stm32·单片机·嵌入式硬件
亿道电子Emdoor15 小时前
【Aitium】PCB导出DXF文件出现eDuplicateRecordName报错
stm32·单片机·嵌入式硬件·altium
巴巴媛6661 天前
STM32学习笔记【38.DHT11实验】
笔记·stm32·学习
深圳市泰凌微电子1 天前
HK航顺 HK32F407RGT7替STM32F405RGT6 微控制器32位MCU
stm32·单片机·嵌入式硬件
小心亦新1 天前
STM32学习16--定时器输出比较2直流电机
stm32·嵌入式硬件·学习