手把手教你玩转ESP8266(原理+驱动)

在嵌入式开发中,无线通信的方式有很多,其中 WIFI 是绕不开的话题。说到 WIFI 通信,就不得不提 ESP8266了。

ESP8266 是一款高性能的 WIFI 串口模块,实现透明传输。只要有一定的串口知识,不需要知道 WIFI 原理就可以上手,在业内应用广泛。

1. 源码下载

本文首发 良许嵌入式网 :https://www.lxlinux.net/e/ ,欢迎关注!

本文所涉及的源码及安装包如下(由于平台限制,请点击以下链接阅读原文下载):

https://www.lxlinux.net/e/stm32/esp8266-tutorial.html

  • STM32F103C8T6模板工程

  • 本文的源码

  • 串口调试助手

  • 网络调试助手

  • CH340驱动

如果不知道如何搭建 STM32 编程环境,不知道如何烧录 STM32 代码,可以阅读这篇文章:

https://www.lxlinux.net/e/stm32/stm32-quick-start-for-beginner.html

如果你连代码都不知道怎么烧录到 STM32 的,可以参考下文,提供了 5 种代码烧录方式:

https://www.lxlinux.net/e/stm32/five-ways-to-flash-program-to-stm32.html

文中所使用的芯片是 STM32F103C8T6 ,配套了一个工程模板,如果你需要自己搭建一个工程模板,可以参考下文:

https://www.lxlinux.net/e/stm32/create-stm32-hal-project-template.html

2. ESP8266介绍

ESP8266 是一个非常强大的 WIFI 模块,可以利用串口与单片机进行通讯,从而编程实现控制 ESP8266。利用 ESP8266 可以访问一些 API,获取天气信息或者完成网络授时,也可以连接云平台进行开发。不过因为是串口传输,速度较慢,不能用来传输图像、视频这些大容量的数据,但是传些传感器数据还是绰绰有余的。

我们常说的 ESP8266 是指 ESP8266 WIFI 模块,它是物联网和嵌入式开发常用的模块,其中 ESP8266 是 WIFI 模块的芯片型号。

ESP8266 有 ESP-01/01S/07/07S/12E/12F/12S 等规格,还有正点原子自研的 ATK-ESP8266 (修改了固件及模组引脚)。

本文用到的是 ESP-01S,长下面这样。这种模组非常便宜,某宝几块钱一个,建议可以买几个囤着。

3. 三种调试方式

ESP8266 已经是一款很成熟的模组了,前文提到,它可以通过串口进行通讯。

既然可以进行串口通讯,那么我们就可以使用以下三种方法进行调试。

  • USB 转 TTL 工具

这玩意儿大家应该非常熟悉了,通常我们用它来打印单片机 log。

当然,配合上位机(比如串口调试助手),我们也可以使用它对一些模组进行调试,比如:ESP8266、4G模组、蓝牙,等等。

如果对这个工具使用不熟悉的小伙伴,可以阅读下文:

【零基础快速上手STM32开发(手把手保姆级教程)】

USB转TTL模块ESP8266
3.3V3.3V
TXDRX
RXDTX
GNDGND

使用 USB 转 TTL 工具调试 ESP8266,可以通过上面的表格进行接线。

3.3V 相接后可能无法启动 ESP8266,这是因为 USB 转 TTL 模组的 3.3V 并没有真的达到 3.3V,莫慌,直接将 ESP8266 的3.3V 引脚接入 USB 转 TTL 的 5V 引脚,如果 ESP8266 会发烫到无法触摸就拔掉,如果温度你手指还能接受,那就没问题,ESP8266 还是没那么脆弱的。

接好线之后,将 USB 端连接到电脑,打开串口调试助手就可以进行调试了。

  • USB 转 ESP8266WIFI 模块

上面的 USB 转 TTL 模组需要你动手去接线,比较麻烦,而且要是线有一根接错了,就无法正常调试了。

而这个模组专门是为了调试 ESP8266 而设计,不需要一个个引脚接线,直接把 ESP8266 往上一插就可以啦,超方便的。同样,USB 端连接电脑,打开串口调试助手就可以进行调试了。

  • 单片机调试

这种就是在项目中最常用的方式了。需要将 ESP8266 接到单片机的任意一个串口,然后再编写代码驱动 ESP8266 ,实现各种业务逻辑。

本文就是手把手教大家编写一个 ESP8266 驱动程序。

上电:正常工作验证

模块拿到手之后,我们需要先确保这个模组是正常的,否则后面的调试、写代码都是白搭。

首先,上电后,蓝色灯微弱闪烁后熄灭,表示正常工作。

还可以更进一步,接好线之后,然后打开串口调试助手发送 AT(并且还要敲一个回车),ESP8266 回复 OK,就是正常启动了。

4. ESP8266工作模式

ESP8266 支持 STA、AP、AP+STA 三种工作模式。

  • STA 模式(Station)

一般用于远距离传输。ESP8266 通过路由器连接互联网,终端设备通过互联网实现对设备的远程控制。简单来说,此时的 ESP8266 可以当作是一个客户端,可以向服务端进行数据的下载与传输。这就类似于,手机/平板/笔记本(客户端)可以通过 WIFI 连接到路由器进行上网。

  • AP 模式(Access Point)

一般用于近距离传输。ESP8266 作为热点,提供无线接入服务、数据访问,一般的无线路由/网桥工作在 AP 模式下,最多支持 4 台设备接入。简单来说,此时的 ESP8266 可以当作是一个服务端。这就类似于,ESP8266 变身为一个路由器,然后手机/平板/笔记本可以通过 WIFI 连接到 ESP8266 进行上网。

  • AP+STA 模式

两种模式的共存模式,可以通过互联网控制可实现无缝切换,方便操作。简单来说,此时的 ESP8266 可以当作是一个路由器既可以做服务端接收也可以当客户端连接路由器,进行联网传输和控制。

5. AT指令介绍

5.1 什么是AT指令?

AT 指令(AT Commands)最早是由发明拨号调制解调器的贺氏公司为了控制拨号调制解调器而发明的控制协议。后来随着网络带宽的升级,速度很低的拨号调制解调器基本退出市场,但是 AT 指令被保留了下来。

在嵌入式开发中,经常是使用 AT 命令去控制各种通讯模块,比如 ESP8266 模块、4G 模块、GPRS 模块等等。一般就是主芯片通过硬件接口(比如串口、SPI)发送 AT 指令给通讯模块,模块接收到数据之后回应响应的数据。

5.2 常用AT指令介绍

AT 指令分为四种类型:

类型格式功能
测试指令AT + < X > = ?查询设置命令或内部程序设置的参数及其取值范围
查询指令AT + < X > ?返回参数的当前值
设置指令AT + < X > = < ... >设置用户自定义的参数值
执行指令AT + < X >执行受模块内部程序控制的变参数不可变

AT 指令有近百条,但常用的就十几条,理解起来也非常简单,现在举例一些常用指令,并使用这些指令一步一步的通过 TCP 连接到远程的服务器实现收发数据。

AT指令功能
AT测试是否正常启动
AT+CWMODE=1设置 STA 模式
AT+CWMODE=2设置 AP 模式
AT+CWMODE=3设置 AP+STA 模式
AT+RST重启生效
AT+CWSAP=”SSID”,”password”,1,4设置 AP 参数:账号为SSID ,密码为password,通道号为 1,加密方式为:WPA_WPA2_PSK
AT+CIPMUX=0开启单连接
AT+CIPMUX=1开启多连接
AT+CIPSERVER=1,8080开启 SERVER 模式,设置端口为 8080
AT+CIPSTART=“TCP”,"192.168.X.XXX”,8080建立 TCP 连接到”192.168.X.XXX”,8080
AT+CIPSTART=“UDP”,“192.168.X.XXX”,8080建立 UDP 连接到”192.168.X.XXX”,8080
AT+CIPCLOSE断开 TCP 连接
AT+CWQAP断开热点
AT+CIPSEND=n开始传输,n表示需要传输的字节数
AT+CIPSEND=0,n向 ID0 发送 n 字节数据包,n的值自己定
AT+CIPMODE=1开启透传模式
AT+CIPSEND开始发送数据
AT+CIPMODE=0退出透传
AT+CWJAP="SSID,“password”加入 WIFI 热点:SSID ,密码为:password
AT+CIFSR查询 ESP8266 的 IP 地址
AT+CIPSTA?查询 ESP8266 的 IP 、网关地址和子网掩码

接下来我们要用串口助手发送 AT 指令,如果你还不会用串口助手,那么动动小手跟我操作:

  1. 插上 USB,选择正确的串口号,正确的串口号是插上 USB 后多出的串口号;
  2. 选择波特率,ESP8266 默认波特率是 115200 ,可以通过 AT 指令修改;
  3. 点击「打开」或者「打开串口」;
  4. 在输入框输入指令,AT 指令要以回车结尾;
  5. 点击「发送」,观察 ESP8266 的返回值;
  6. 使用完点「断开」或者「关闭串口」。

不一定要用我的串口助手,别的串口助手也可以(比如正点原子开发的串口助手,甚至你自己写一个也行),都是一样的。

如果已经插上 USB,选择了正确的串口号,但是出现串口打不开并输出「【ERROR】Cannot set COM port parameters」 的情况,可能是 CH340 驱动还没安装,或者需要卸载重新安装一下。教你解决:

  1. 先点「断开」,断开串口;
  2. 打开 CH340 驱动安装程序,我文章开头有提供;
  3. 如果你没有安装过,点击「安装」;如果你安装过,点击「卸载」再点击「安装」;
  4. 安装好后拔插一下 USB,看看串口号有没有变,有变更换一下串口号;
  5. 最后点「打开」或者「打开串口」就可以啦。

如果还不明白的,可以参考下文,有图文教程:

【零基础快速上手STM32开发(手把手保姆级教程)】

5.2.1 测试模块是否正常(AT)

发送 AT,ESP8266 回复 OK,就是正常启动了。

5.2.2 开启/关闭回显(ATE1/ATE0)

发送了指令 AT,模块回复了「AT OK」,即模块将发送过来的指令原封不动的先复述了一遍后接着发送有效回复,我们称这种复述为 回显

发送 ATE0,关闭回显

发送 ATE1,开启回显

5.2.3 设置AP模式及AP参数(AT+CWMODE,AT+CWSAP)

发送 AT+CWMODE?,查询模块当前处于哪一种模式;

发送 AT+CWMODE=1,设置 STA 模式;

发送 AT+CWMODE=2,设置 AP 模式;

发送 AT+CWMODE=3,设置 AP+STA 模式。

如果当前为 AP 模式,那么发送 AT+CWSAP="SSID","password",通道,加密方式 ,可以设置热点。这个过程相当于给路由器设置热点名称及密码,方便手机连接。

例如:发送 AT+CWSAP="ESP8266-liangxu","12345678",5,3 ,则可以将热点名设置为 ESP8266-liangxu ,密码为 12345678,使用通道 5 ,加密方式为 WPA2_PSK(1-WEP,2-WPA_PSK,3-WPA2_PSK,4-WPA_WPA2_PSK),这里的通道对应的就是不同的射频频率,如果同一空间内存在相同通道的 WIFI 信号,将会产生干扰,影响上网质量,因此可以设置通道来避免这种干扰,常用的通道有 1、6、11,因为这三个通道互不产生干扰。

5.2.4 设置为STA模式(AT+CWMODE=1,AT+CWJAP,AT+CIFSR)

发送 AT+CWMODE=1,设置 STA 模式;

发送 AT+CWJAP="SSID","password",连接路由器;

发送 AT+CIPSTA?,路由器分配给 ESP8266 的局域网 IP 以及网关地址和子网掩码;

发送 AT+CIFSR,查询 ESP8266 的 IP 地址信息。

5.2.5 TCP透传
5.2.5.1 准备工作

实现 TCP 透传需要搭建一个 TCP 服务器,这里我们就使用网络调试助手 + 自己的电脑就好。我的网络调试助手是正点原子的,大家不一定要用我的,只要是网络助手都可以。

首先我们需要知道自己电脑的 IP 地址,有两种方式:

方法1:打开电脑的设置:

方法2:使用命令提示符:

打开网络调试助手,跟我配置,超快的。端口号 TCP 协议一般填8080。

5.2.5.2 正式开始

接下来我们利用串口助手将 ESP8266 连接到 TCP 服务器。

发送 AT+CIPSTART="协议模式","服务端IP地址",端口号 ,建立连接,协议模式有 TCP 和 UDP ;

因为我们刚刚搭建的是 TCP 服务器,服务器 IP 地址是 192.168.1.27,所以我们发送 AT+CIPSTART="TCP","192.168.1.27",8080 。如果不出意外,过一会儿 ESP8266 就连接上 TCP 服务器了,将返回 CONNECT OK 。

但这个时候,我们再在输入框发送内容的话,依然是默认为指令。如果我们想把数据直接发送给 TCP 服务器,那么就需要开启透传模式。

所谓的透传模式,可以视为 ESP8266 为透明状态,客户端发送的信息直接就传输给服务端。

我们需要先发送 AT+CIPMODE=1,开启透传模式。然后,再发送 AT+CIPSEND,才真正开始透传发送。

此时,你发送的任何数据,就直接传输到服务器了。

退出透传:先发送 +++(不要带回车),再发送 AT+CIPMODE=0

如果不退出透传,发出来的就算是 AT 指令,它也会被认为是普通字符串,直接透传给对方。

AT+CWCLOSE,断开 TCP 连接。

AT+CWQAP,断开热点。

6. 编程实战

6.1 硬件接线

本教程使用的硬件如下:

  • 单片机:STM32F103C8T6

  • WiFi模块:ESP-01S

  • 串口:USB 转 TTL

  • 烧录器:ST-LINK V2。

接线可参照下表:

ESP8266STM32USB 转 TTL
3V33.3
TXA3
RXA2
GNDG
A10TX
A9RX
GGND

烧录的时候接线如下表,如果不会烧录的话可以看我之前的文章【STM32下载程序的五种方法】。

ST-Link V2STM32
SWCLKSWCLK
SWDIOSWDIO
GNDGND
3.3V3V3

其中 USB 转 TTL 连接的是 STM32 的串口1(A9和A10),用来打印 STM32 的输出;STM32 的串口2(A2和A3),用来控制 ESP8266。

接好就像这样:

6.2 模板工程加载ESP8266模块代码

打开模板工程和 ESP8266 驱动源码。

复制好后打开工程。

跟着我的贪吃蛇点点点:)

6.3 串口通讯实现

实现向串口发送数据,并等待返回值。ESP8266 的 TX 和 RX 定义在串口2。

  1. 定义串口句柄 g_uart_handle ,并调用 HAL_UART_Init 进行初始化。
UART_HandleTypeDef g_uart_handle;void esp8266_uart_init(uint32_t baudrate)
{g_uart_handle.Instance          = ESP8266_UART_INTERFACE;       /* ESP8266 UART */g_uart_handle.Init.BaudRate     = baudrate;                     /* 波特率 */g_uart_handle.Init.WordLength   = UART_WORDLENGTH_8B;           /* 数据位 */g_uart_handle.Init.StopBits     = UART_STOPBITS_1;              /* 停止位 */g_uart_handle.Init.Parity       = UART_PARITY_NONE;             /* 校验位 */g_uart_handle.Init.Mode         = UART_MODE_TX_RX;              /* 收发模式 */g_uart_handle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;          /* 无硬件流控 */g_uart_handle.Init.OverSampling = UART_OVERSAMPLING_16;         /* 过采样 */HAL_UART_Init(&g_uart_handle);                                  /* 使能ESP8266 UART */
}

其中,ESP8266_UART_INTERFACE 是宏定义,指代的就是 USART2

传入参数 baudrate 可以定义该串口的波特率。

  1. 初始化串口底层函数,调用 HAL_UART_MspInit 函数。

注意最后一行,需要调用 __HAL_UART_ENABLE_IT 函数使能接收中断。

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{GPIO_InitTypeDef gpio_init_struct;if (huart->Instance == USART_UX)                            /* 如果是串口1,进行串口1 MSP初始化 */{....// 省略串口1相关代码....}else if (huart->Instance == ESP8266_UART_INTERFACE)                 /* 如果是ESP8266 UART */{ESP8266_UART_TX_GPIO_CLK_ENABLE();                              /* 使能UART TX引脚时钟 */ESP8266_UART_RX_GPIO_CLK_ENABLE();                              /* 使能UART RX引脚时钟 */ESP8266_UART_CLK_ENABLE();                                      /* 使能UART时钟 */gpio_init_struct.Pin    = ESP8266_UART_TX_GPIO_PIN;             /* UART TX引脚 */gpio_init_struct.Mode   = GPIO_MODE_AF_PP;                          /* 复用推挽输出 */gpio_init_struct.Pull   = GPIO_NOPULL;                              /* 无上下拉 */gpio_init_struct.Speed  = GPIO_SPEED_FREQ_HIGH;                     /* 高速 */HAL_GPIO_Init(ESP8266_UART_TX_GPIO_PORT, &gpio_init_struct);    /* 初始化UART TX引脚 */gpio_init_struct.Pin    = ESP8266_UART_RX_GPIO_PIN;             /* UART RX引脚 */gpio_init_struct.Mode   = GPIO_MODE_INPUT;                          /* 输入 */gpio_init_struct.Pull   = GPIO_NOPULL;                              /* 无上下拉 */gpio_init_struct.Speed  = GPIO_SPEED_FREQ_HIGH;                     /* 高速 */HAL_GPIO_Init(ESP8266_UART_RX_GPIO_PORT, &gpio_init_struct);    /* 初始化UART RX引脚 */HAL_NVIC_SetPriority(ESP8266_UART_IRQn, 0, 0);                  /* 抢占优先级0,子优先级0 */HAL_NVIC_EnableIRQ(ESP8266_UART_IRQn);                          /* 使能UART中断通道 */__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);                          /* 使能UART接收中断 */}
}
  1. 使用接收中断+超时判断,完成数据接收。

由于 ESP8266 通过串口返回的数据长度不固定,所以我们可以使用接收中断+超时判断的方法完成数据接收。具体方法可以参考下文:

【STM32串口接收不定长数据(接收中断+超时判断)】

在串口中断服务函数里,我们可以将接收到的字符保存在接收缓冲区里 g_uart_rx_buf ,并定义一个变量 esp8266_cnt 计算总共收到了多少个字符。

void ESP8266_UART_IRQHandler(void)
{uint8_t receive_data = 0;   if(__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_RXNE) != RESET){if(esp8266_cnt >= sizeof(g_uart_rx_buf))esp8266_cnt = 0; //防止串口被刷爆HAL_UART_Receive(&g_uart_handle, &receive_data, 1, 1000);//串口2接收1位数据g_uart_rx_buf[esp8266_cnt++] = receive_data;  }HAL_UART_IRQHandler(&g_uart_handle);
}

假如一帧的数据接收完成了,那么 esp8266_cnt 变量的值应该维持不变。

我们通过 while 死循环不停计算当前收到多少个字符,当前统计的值计算在 esp8266_cnt 变量里,定义另一个变量 esp8266_cntPre ,用于记录上一次统计接收到的数据的长度,如果本次统计数据长度跟上一次一样的话就说明数据接收完成了。代码如下:

uint8_t esp8266_wait_receive(void)
{if(esp8266_cnt == 0)                             //如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数return ESP8266_ERROR;if(esp8266_cnt == esp8266_cntPre) {                //如果上一次的值和这次相同,则说明接收完毕esp8266_cnt = 0;                            //清0接收计数return ESP8266_EOK;                            //返回接收完成标志}esp8266_cntPre = esp8266_cnt;                    //置为相同return ESP8266_ERROR;                            //返回接收未完成标志
}

当然,接收到的数据使用完成之后,我们就应该清空接收缓冲区,并将计数器置 0 ,方便下一次接收。

void esp8266_clear(void)
{memset(g_uart_rx_buf, 0, sizeof(g_uart_rx_buf));esp8266_cnt = 0;
}

接下来,就是最关键的一个函数了。我们使用这个函数通过串口向 ESP8266 发送一个字符串,并循环等待我们所期待得到的字符串。

在下面这个函数里,cmd 变量是我们向 ESP8266 发送的字符串,res 变量是我们期待得到的回复。

比如,我们向 ESP8266 发送 AT 这个字符串,那么 ESP8266 如果正常的话应该会回复 OK 。此时,cmd 就是 AT ,而 res 就是 OK

uint8_t esp8266_send_command(char *cmd, char *res)
{uint8_t timeOut = 250;esp8266_clear();HAL_UART_Transmit(&g_uart_handle, (unsigned char *)cmd, strlen((const char *)cmd), 100);while(timeOut--) {if(esp8266_wait_receive() == ESP8266_EOK) {                        //如果收到数据if(strstr((const char *)g_uart_rx_buf, res) != NULL)        //如果检索到关键词return ESP8266_EOK;}delay_ms(10);}return ESP8266_ERROR;
}

6.4 编程实现AT指令交互

接下来,我们就可以使用 esp8266_send_command 发送 AT 指令并确定 ESP8266 回复是否正确。以代码方式实现各个 AT 指令,例子如下:

uint8_t esp8266_at_test(void)
{return esp8266_send_command("AT\r\n", "OK");
}uint8_t esp8266_sw_reset(void)
{return esp8266_send_command("AT+RST\r\n", "OK");
}uint8_t esp8266_set_mode(uint8_t mode)
{switch (mode) {case ESP8266_STA_MODE:return esp8266_send_command("AT+CWMODE=1\r\n", "OK");    /* Station模式 */case ESP8266_AP_MODE:return esp8266_send_command("AT+CWMODE=2\r\n", "OK");    /* AP模式 */case ESP8266_STA_AP_MODE:return esp8266_send_command("AT+CWMODE=3\r\n", "OK");    /* AP+Station模式 */default:return ESP8266_EINVAL;}
}

由于 AT 指令有很多,这里只截取了其中的一部分,完整的可以参考我提供的代码。

6.5 编程实现STA模式

STA 模式实现思路如下:

  1. 进入 STA 模式(要重启生效);
  2. 设置单路连接;
  3. 连接 WIFI(注意 ESP8266 和服务端要在同一网络内);
  4. 浅查一下 ESP8266 的 IP 地址,不查也可以;
  5. 连接TCP服务器;
  6. 开启透传。
uint8_t esp8266_single_connection(void)
{return esp8266_send_command("AT+CIPMUX=0\r\n", "OK");
}uint8_t esp8266_join_ap(char *ssid, char *pwd)
{char cmd[64];sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd);return esp8266_send_command(cmd, "WIFI GOT IP");
}uint8_t esp8266_get_ip(char *buf)
{char *p_start;char *p_end;if (esp8266_send_command("AT+CIFSR\r\n", "STAIP") != ESP8266_EOK)return ESP8266_ERROR;p_start = strstr((const char *)g_uart_rx_buf, "\"");p_end = strstr(p_start + 1, "\"");*p_end = '\0';sprintf(buf, "%s", p_start + 1);return ESP8266_EOK;
}uint8_t esp8266_connect_tcp_server(char *server_ip, char *server_port)
{char cmd[64];sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%s\r\n", server_ip, server_port);return esp8266_send_command(cmd, "CONNECT");
}uint8_t esp8266_enter_unvarnished(void)
{uint8_t ret;ret  = esp8266_send_command("AT+CIPMODE=1\r\n", "OK");ret += esp8266_send_command("AT+CIPSEND\r\n", ">");if (ret == ESP8266_EOK)return ESP8266_EOK;elsereturn ESP8266_ERROR;
}/*** @brief       ESP8266初始化* @param       baudrate: ESP8266 UART通讯波特率* @retval      ESP8266_EOK  : ESP8266初始化成功,函数执行成功*              ESP8266_ERROR: ESP8266初始化失败,函数执行失败*/
uint8_t esp8266_init(uint32_t baudrate)
{char ip_buf[16];esp8266_uart_init(baudrate);                /* ESP8266 UART初始化 *//* 让WIFI退出透传模式 */while(esp8266_exit_unvarnished())delay_ms(500);printf("1.AT\r\n");while(esp8266_at_test())delay_ms(500);printf("2.RST\r\n");while(esp8266_sw_reset())delay_ms(500);while(esp8266_disconnect_tcp_server())delay_ms(500);printf("3.CWMODE\r\n");while(esp8266_set_mode(ESP8266_STA_MODE))delay_ms(500);printf("4.AT+CIPMUX\r\n");  //设置单路连接模式,透传只能使用此模式while(esp8266_multi_connection())delay_ms(500);printf("5.CWJAP\r\n");      //连接WIFIprintf("%s\r\n",WIFI_SSID); while(esp8266_join_ap(WIFI_SSID, WIFI_PWD))delay_ms(1000);printf("6.CIFSR\r\n");while(esp8266_get_ip(ip_buf))delay_ms(500);printf("ESP8266 IP: %s\r\n", ip_buf);printf("7.CIPSTART\r\n");while(esp8266_connect_tcp_server(TCP_SERVER_IP, TCP_SERVER_PORT))delay_ms(500);printf("8.CIPMODE\r\n");while(esp8266_enter_unvarnished())delay_ms(500);printf("ESP8266初始化完成\r\n");return ESP8266_EOK;
}

代码完成,编译,烧录,打开串口,串口输出,实现效果当当当:

6.6 编程实现AP模式

AP 模式实现思路很简单:

  1. 进入 AP 模式(要重启生效);
  2. 设置 AP 参数;
  3. 开启多连接或单连接。
uint8_t esp8266_set_ap(char *ssid, char *pwd)
{char cmd[64];sprintf(cmd, "AT+CWSAP=\"%s\",\"%s\",5,3\r\n", ssid, pwd);return esp8266_send_command(cmd, "OK");
}uint8_t esp8266_multi_connection(void)
{return esp8266_send_command("AT+CIPMUX=1\r\n", "OK");
}uint8_t esp8266_init(uint32_t baudrate)
{char ip_buf[16];esp8266_uart_init(baudrate);                /* ESP8266 UART初始化 *//* 让WIFI退出透传模式 */while(esp8266_exit_unvarnished())delay_ms(500);printf("1.AT\r\n");while(esp8266_at_test())delay_ms(500);printf("2.RST\r\n");while(esp8266_sw_reset())delay_ms(500);while(esp8266_disconnect_tcp_server())delay_ms(500);printf("3.CWMODE\r\n");while(esp8266_set_mode(ESP8266_AP_MODE))delay_ms(500);printf("4.CWSAP\r\n");      //设置APprintf("%s\r\n",WIFI_SSID); while(esp8266_set_ap(WIFI_SSID, WIFI_PWD))delay_ms(1000);printf("5.AT+CIPMUX\r\n");  //设置多路连接模式while(esp8266_multi_connection())delay_ms(500);printf("ESP8266_Init OK\r\n");return ESP8266_EOK;
}

代码完成,烧录,打开串口,串口输出,实现效果当当当:

6.7 编程实现AP+STA模式

AP+STA 模式使用不多,就是前两个的结合,这里就不多介绍了。仿照 STA 模式和 AP 模式写相应的 AT 指令代码就好啦,思路如下,需要注意的是要启动多连接:

  1. 设置为 AP+STA 模式(要重启生效);
  2. AT+CWJAP=”SSID”,”password”,连接WIFI(注意 ESP8266 和服务端要在同一网络内);
  3. AT+CWSAP="SSID","password",通道,加密方式,设置AP热点;
  4. AT+CIPMUX=1,启动多连接;
  5. AT+CIPSERVER=1,8080,打开服务器端口为8080。
uint8_t esp8266_join_ap(char *ssid, char *pwd)
{char cmd[64];sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, pwd);return esp8266_send_command(cmd, "WIFI GOT IP");
}uint8_t esp8266_set_ap(char *ssid, char *pwd)
{char cmd[64];sprintf(cmd, "AT+CWSAP=\"%s\",\"%s\",5,3\r\n", ssid, pwd);return esp8266_send_command(cmd, "OK");
}uint8_t esp8266_multi_connection(void)
{return esp8266_send_command("AT+CIPMUX=1\r\n", "OK");
}uint8_t esp8266_open_server()
{return esp8266_send_command("AT+CIPSERVER=1,8080\r\n", "OK");
}uint8_t esp8266_init(uint32_t baudrate)
{char ip_buf[16];esp8266_uart_init(baudrate);                /* ESP8266 UART初始化 *//* 让WIFI退出透传模式 */while(esp8266_exit_unvarnished())delay_ms(500);/* STA+AP模式 */printf("1.AT\r\n");while(esp8266_at_test())delay_ms(500);printf("2.RST\r\n");while(esp8266_sw_reset())delay_ms(500);while(esp8266_disconnect_tcp_server())delay_ms(500);printf("3.CWMODE\r\n");while(esp8266_set_mode(ESP8266_STA_AP_MODE))delay_ms(500);printf("4.CWJAP\r\n");      //连接WIFIprintf("%s\r\n",WIFI_SSID); while(esp8266_join_ap(WIFI_SSID, WIFI_PWD))delay_ms(1000);printf("5.CWSAP\r\n");      //设置APwhile(esp8266_set_ap("ESP8266-liangxu", "12345678"))delay_ms(1000);printf("6.AT+CIPMUX\r\n");  //设置多路连接模式while(esp8266_multi_connection())delay_ms(500);printf("7.CIPSERVER\r\n");  //打开服务器端口8080while(esp8266_open_server())delay_ms(500);printf("ESP8266_Init OK\r\n");return ESP8266_EOK;
}

代码完成,编译,烧录,打开串口,串口输出,实现效果当当当:

esp8266.h文件内容如下:

#ifndef __ESP8266_H__
#define __ESP8266_H__#include <stdint.h>
#include "usart.h"extern UART_HandleTypeDef g_uart_handle;/* 引脚定义 */
#define ESP8266_UART_TX_GPIO_PORT           GPIOA
#define ESP8266_UART_TX_GPIO_PIN            GPIO_PIN_2
#define ESP8266_UART_TX_GPIO_CLK_ENABLE()   do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PC口时钟使能 */#define ESP8266_UART_RX_GPIO_PORT           GPIOA
#define ESP8266_UART_RX_GPIO_PIN            GPIO_PIN_3
#define ESP8266_UART_RX_GPIO_CLK_ENABLE()   do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PD口时钟使能 */#define ESP8266_UART_INTERFACE              USART2
#define ESP8266_UART_IRQn                   USART2_IRQn
#define ESP8266_UART_IRQHandler             USART2_IRQHandler
#define ESP8266_UART_CLK_ENABLE()           do{ __HAL_RCC_USART2_CLK_ENABLE(); }while(0) /* UART2时钟使能 *//* UART收发缓冲大小 */
#define ESP8266_UART_RX_BUF_SIZE            128
#define ESP8266_UART_TX_BUF_SIZE            64/* 错误代码 */
#define ESP8266_EOK                         0   /* 没有错误 */
#define ESP8266_ERROR                       1   /* 通用错误 */
#define ESP8266_ETIMEOUT                    2   /* 超时错误 */
#define ESP8266_EINVAL                      3   /* 参数错误 *//* 工作模式 */
#define ESP8266_STA_MODE                    1
#define ESP8266_AP_MODE                     2
#define ESP8266_STA_AP_MODE                 3#define WIFI_SSID                           "HuaweiAP-1ED0"
#define WIFI_PWD                            "87654321"#define TCP_SERVER_IP                       "192.168.1.27"
#define TCP_SERVER_PORT                     "8080"uint8_t esp8266_init(uint32_t baudrate);
void esp8266_clear(void);
void esp8266_uart_printf(char *fmt, ...);
#endif

7. 小结

通过学习和实践,希望大家能够了解并掌握 ESP8266 的特性和使用,从而更好地应用于嵌入式开发。无论是构建智能家居系统还是开发物联网设备,ESP8266 都可以成为您的得力助手,让我们一起玩转 ESP8266,love and peace!


另外,想进大厂的同学,一定要好好学算法,这是面试必备的。这里准备了一份 BAT 大佬总结的 LeetCode 刷题宝典,很多人靠它们进了大厂。

刷题 | LeetCode算法刷题神器,看完 BAT 随你挑!

有收获?希望老铁们来个三连击,给更多的人看到这篇文章

推荐阅读:

  • 程序员必备编程资料大全
  • 程序员必备软件资源

欢迎关注我的博客:良许嵌入式教程网,满满都是干货!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/214735.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

作为一个产品经理带你了解Axure的安装和基本使用

1.Axure的简介 Axure是一种强大的原型设计工具&#xff0c;它允许用户创建交互式的、高保真度的原型&#xff0c;以及进行用户体验设计和界面设计。Axure可以帮助设计师和产品经理快速创建和共享原型&#xff0c;以便团队成员之间进行沟通和反馈。Axure提供了丰富的交互组件和功…

Spring--10--Spring Bean的生命周期

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.Spring Bean1.1 什么是 Bean简而言之&#xff0c;bean 是由 Spring IoC 容器实例化、组装和管理的对象。 1.2 Spring框架管理Bean对象的优势 2.Bean的生命周期实例…

西工大网络空间安全学院计算机系统基础实验二(phase_2下——漫漫深夜过后的黎明!!!)

内存地址内存地址中的数注释指向这块内存的寄存器0xffffd0e8函数phase_2的栈帧0xffffd0e40xffffd0f4函数phase_2的栈帧0xffffd0e00x5655b7b0函数phase_2的栈帧0xffffd0dc0x565566ca函数read_six_numbers的返回地址&#xff0c;函数phase_2的栈帧0xffffd0d80x5655af64旧%ebx的值…

SpringIOC之ConditionEvaluator

博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…

一文读懂MySQL基础知识文集(8)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

单目相机测距(3米范围内)二维码实现方案(python代码 仅仅依赖opencv)

总体思路:先通过opencv 识别二维码的的四个像素角位置,然后把二维码的物理位置设置为 cv::Point3f(-HALF_LENGTH, -HALF_LENGTH, 0), //tl cv::Point3f(HALF_LENGTH, -HALF_LENGTH, 0), //tr cv::Point3f(HALF_LENGTH, HALF_LENGTH, 0), //br cv::P…

软件运行原理 - 内存模型 - 栈内存

说明 C/C软件运行时&#xff0c;内存根据使用方式的不同分为堆内存和栈内存&#xff0c;栈内存使用有以下特征&#xff1a; 栈内存使用&#xff08;申请、释放&#xff09;由系统自动分配和释放&#xff0c;程序员不用做任何操作。栈内存重复使用&#xff0c;进入函数时数据入…

什么是特征图?

在卷积神经网络&#xff08;CNN&#xff09;中&#xff0c;特征图是在传递给卷积层的图像上发生卷积操作后卷积层的输出。 特征图是如何形成的&#xff1f; 在上面的插图中&#xff0c;我们可以看到特征图是如何从提供的输入图像中形成的。 要发送到卷积层的图像是一个包含像…

微服务网关组件Gateway实战

1. 需求背景 在微服务架构中&#xff0c;通常一个系统会被拆分为多个微服务&#xff0c;面对这么多微服务客户端应该如何去调用呢&#xff1f;如果根据每个微服务的地址发起调用&#xff0c;存在如下问题&#xff1a; 客户端多次请求不同的微服务&#xff0c;会增加客户端代码…

聚首引领行业风潮!聚首品牌联动资源价值平台发布会正式启航

2023年12月10日&#xff0c;由杭州建筑装饰学会、浙江聚首联优材料科技有限公司主办&#xff0c;天尚设计集团、公和设计集团、铭扬工程设计集团、地标设计集团、上宸工程设计集团、华坤建筑设计院、广厦建筑设计研究院、上海传承博华建筑规划设计院、航冠工程设计院、浙江鸿能…

设计模式——建造者模式(创建型)

引言 生成器模式是一种创建型设计模式&#xff0c; 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。 问题 假设有这样一个复杂对象&#xff0c; 在对其进行构造时需要对诸多成员变量和嵌套对象进行繁复的初始化工作。 这些初始化代码…

Python3开发环境的搭建

1&#xff0c;电脑操作系统的确认 我的是win10、64位的&#xff0c;你们的操作系统可自寻得。 2&#xff0c;Python安装包的下载 &#xff08;1&#xff09;浏览器种输入网址&#xff1a;https://www.python.org 选择对应的系统&#xff08;我的是win10/64位) &#xf…

设计模式(二)-创建者模式(5)-建造者模式

一、为何需要建造者模式&#xff08;Builder&#xff09;? 在软件系统中&#xff0c;会存在一个复杂的对象&#xff0c;复杂在于该对象包含了很多不同的功能模块。该对象里的各个部分都是按照一定的算法组合起来的。 为了要使得复杂对象里的各个部分的独立性&#xff0c;以及…

腾讯物联网平台之规则引擎

1.腾讯物联网平台简介 腾讯云物联网开发平台&#xff08;IoT Explorer&#xff09;为客户提供便捷的物联网开发工具与服务&#xff0c;助力客户更高效的完成设备接入&#xff0c;并为客户提供物联网应用开发及场景服务能力&#xff0c;帮助客户高效、低成本构建物联网应用。  …

SpringBoot集成系列--RabbitMQ

文章目录 一、代码1、添加依赖2、配置RabbitMQ连接3、RabbitMQ配置4、创建生产者5、创建消费者6、测试 二、遇到的问题1、Channel shutdown2、收不到信息3、安装RabbitMQ&#xff0c;无法访问控制台访问 一、代码 1、添加依赖 在pom.xml文件中添加RabbitMQ的相关依赖 <de…

Leetcode—228.汇总区间【简单】

2023每日刷题&#xff08;五十六&#xff09; Leetcode—228.汇总区间 解题思路 我们可以用双指针left 和 right找出每个区间的左右端点。 遍历数组&#xff0c;当right 1< n 且 nums[right1]nums[right]1 时&#xff0c;指针right向右移动&#xff0c;否则区间 [left, …

51.Go操作kafka示例(kafka-go库)

文章目录 一、简介二、生产者三、消费者 代码地址&#xff1a;https://gitee.com/lymgoforIT/golang-trick/tree/master/31-kafka-go 一、简介 之前已经介绍过一个操作kafka的go库了&#xff0c;28.windows安装kafka&#xff0c;Go操作kafka示例&#xff08;sarama库&#xf…

基于JavaWeb+SpringBoot+Vue在线拍卖系统的设计和实现

基于JavaWebSpringBootVue在线拍卖系统系统的设计和实现 源码获取入口Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 Lun文目录 摘 要 1 Abstract 1 1 系统概述 4 1.1 概述 4 1.2课题意义 4 1.3 主要内容 4 2 …

C++新经典模板与泛型编程:策略技术中的算法策略

策略技术中的算法策略 在之前博客中funcsum()函数模板中&#xff0c;实现了对数组元素的求和运算。求和在这里可以看作一种算法&#xff0c;扩展一下思路&#xff0c;对数组元素求差、求乘积、求最大值和最小值等&#xff0c;都可以看作算法。而当前的funcsum()函数模板中&…

MySQL使用教程

数据构成了我们日益数字化的社会基础。想象一下&#xff0c;从移动应用和银行系统到搜索引擎&#xff0c;再到如 ChatGPT 这样的先进人工智能聊天机器人&#xff0c;这些工具若没有数据支撑&#xff0c;将寸步难行。你有没有好奇过这些海量数据都存放在哪里呢&#xff1f;答案正…