17 STM32基础学习 ESP8266-WIFI

学习ESP8266, 下面我们以使用最多的ESP-12,是ESP8266其中的一款芯片。**通过先了解ESP8266,后面我们有详细的项目进行操作。**

ESP8266-12F是ESP8266-12的增强版,完善外围电路,四层板板工艺,增强阻抗匹配,信号输出更佳,无论是稳定性还是抗干扰能力,PCB天线经过专业实验室测试,匹配,经过ROHS认证,都得到了大幅度的提升!对于之前选择ESP-12的用户,即使已经做出产品也没关系,增强版完全兼容之前固件,引脚在ESP-12的基础上又新增六个IO口、SPI口引出,开发更加便捷,应用更加广泛!

例如我们需要的D1 min:

ESP8266简介

ESP8266是一款高性能的UART-WiFi(串口-无线)模块,与MCU(或其他串口设备)通信,内置TCP/IP协议栈,能够实现串口与WIFI之间的转换。通过ESP8266模块,传统的串口设备只是需要简单的串口配置,即可通过网络(WIFI)传输自己的数据。ESP8266模块支持LVTTL串口,兼容3.3V和5V单片机系统,可以很方便的与你的产品进行连接。模块支持串口转WIFI STA、串口转AP和WIFI STA+WIFI AP的模式,从而快速构建串口-WIFI数据传输方案,方便你的设备使用互联网传输数据。

ESP8266模块基本特性

ESP8266模块的功能特性

ESP8266模块电气特性

ESP8266 的 AT指令

AT指令是应用于终端设备与PC应用之间的连接与通信的指令,说白了,AT指令就是大家定义好的,能表达特殊意义的字符串,每条AT命令中只能包含一条AT指令。

AT指令用法

  • 1、测试命令(Test Command)

仅仅发送指令 “AT” 即测试ESP8266模块是否准备好,若准备好则响应“OK”。

  • 2、读取命令(Read Command)

在AT指令后面加上“=?”即构成测试命令。例如“AT+MODE?”,会列举当前是什么模式。

  • 3、执行命令(Execute Command)

在AT指令后面加上“=”再接上相应的参数即可,例如“AT+MODE=NORMAL”,将当前模式设置为正常模式。对于一些没有参数的指令则不需要加参数, 比如”AT+RESET”。

AP/STA模式

  • AP: 即无线接入点,是无线网络的中心节点,我们常使用的路由器就是一个AP。ESP8266 可以工作在AP模式,设置为AP模式、开启热点之后就可以用手机来连接 ESP8266。
  • STA: 每一个连接到无线网络的终端都可以理解为一个STA。ESP8266 也可以工作在STA模式,配置为STA模式之后就可以连接路由器的WiFi。

TCP/UDP/透传

TCP

TCP是一种面向连接的,提供可靠交付服务和全双工通信的,基于字节流的端到端的传输层通信协议。

  • TCP在传输数据之前必须先建立连接,数据传输结束后要释放连接。
  • 每一条TCP连接只能有2个端点,故TCP不提供广播或多播服务。
  • TCP提供可靠交付,通过TCP连接传输的数据,无差错、不丢失、不重复、并且按序到达。
  • TCP是面向字节流的。虽然应用进程和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。TCP并不知道所传输的字节流的含义。

UDP

UDP是一种无连接的,尽最大努力交付的,基于报文的端到端的传输层通信协议。

  • UDP,在发送数据之前不需要建立连接。
  • UDP不保证可靠交付,主机不需要位置复杂的连接状态。
  • UDP是面向报文的。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的的边界,即应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。在接收端,UDP一次交付一个完整的报文。
  • UDP没有拥塞控制,网络出现的拥塞不会使源主机的发送速率降低。
  • UDP支持一对一、一对多、多对一和多对多的交互通信。
  • UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短。

ESP8266 使用(下面我们以D1 mini为例子)

D1 mini模块

所以IO工作电平为3.3V,可瞬间承受5V除D0外,所有IO都支持中断,PWM,I2C以及1-wire

ESP12F 介绍

ESP8266-12F WIFI 模块高性能串口 WIFI 模块,通过 FCC,CE 认证,可直接用于出口型产品里面。模块内嵌 TCP/IP 协议,可以实现串口、WIFI 之间的数据传输转换传输。

模块外观图

==模块引脚描述==

功能说明

ESP8266 模块支持 STA/AP/STA+AP 三种工作模式

  • STA 模式:ESP8266 模块通过路由器连接互联网,手机或电脑通过互联网实现对设备的远程控制。
  • AP 模式:默认模式 ATK_ESP8266 模块作为热点,实现手机或电脑直接与模块通信,实现局域网无线控制。
  • STA+AP 模式两种模式的共存模式,(STA 模式)即可以通过路由器连接到互联网,并通过互联网控制设备;(AP 模式)也可作为 wifi 热点,其他 wifi 设备连接到模块。这样实现局域网和广域网的无缝切换,方便操作。

透传模式

ESP8266 模块仅在 TCP Client UDP,支持透传模式。

与STM32单片机连接

指令结构

每条指令可以细分为四种命令

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

注意:

  • 1,不是每条指令都具备上述 4 类指令
  • 2, [ ]内数据为缺省值,不必填写或可能不显示
  • 3, 使用双引号表示字符串数据.”string”

例如,AT+CWJAP=”ESP8266”,”15201314”

  • 4, 波特率 15200
  • 5, 输入以回车换行结尾”\r\n”

基础 AT 指令

AT 指令简介

在 AT 模式下可以通过串口的 AT 指令对系统参数做配置。指令格式如下:

AT+<COMMAND>=<VALUE>\r\n

根据不同指令,模块将返回不同的返回值。其中\r\n 为回车换行符,用 16 进制表示,

就是 0X0D,0X0A。

例如:”查询当前模块的 WIFI 模式。

“AT+CWMODE?\r\n

例如:”设置模块 WIFI 模式为 AP+STA 模式。

“AT+CWMODE=3\r\n

==基础 AT 指令列表==

AT 测试指令
AT+RST 重启模块
AT+GMR 查看版本信息
ATE 开关回显功能
AT+RESTORE 恢复出厂设置
AT+UART 设置串口配置

AT

AT+RST

AT+GMR

ATE

AT+RESTORE

AT+UART

WIFI 功能 AT 指令

WIFI 功能 AT 指令列表:

指令 描述
AT+CWMODE 选择 WIFI 应用模式
AT+CWJAP 加入 AP
AT+CWLAP 列出当前可用 AP
AT+CWQAP 退出与 AP 的连接
AT+CWSAP 设置 AP 模式下的参数
AT+CWLIF 查看已接入设备的 IP
AT+CWDHCP 设置 DHCP 开关
AT+CWAUTOCONN 设置 STA 开机自动连接到 wifi
AT+CIPSTAMAC 设置 STA 的 MAC 地址
AT+CIPAPMAC 设置 AP 的 MAC 地址
AT+CIPSTA 设置 STA 的 IP 地址
AT+CIPAP 设置 AP 的 IP 地址
AT+SAVETRANSLINK 保存透传连接到 Flash
AT+CWSMARTSTART 启动智能连接
AT+CWSMARTSTOP 停止智能连接

AT+CWMODE

AT+CWJAP

AT+CWLAP

AT+CWQAP

AT+CWSAP

AT+CWLIF

TCP/IP 工具箱 AT 指令

TCP/IP 工具箱 AT 指令列表:

指令 描述
AT+CIPSTATUS 获得连接状态
AT+CIPSTART 建立 TCP 连接或注册 UDP 端口号
AT+CIPSEND 发送数据
AT+CIPCLOSE 关闭 TCP 或 UDP
AT+CIFSR 获取本地 IP 地址
AT+CIPMUX 启动多连接
AT+CIPSERVER 配置为服务器
AT+CIPMODE 设置模块传输模式
AT+CIPSTO 设置服务器超时时间
AT+CIUPDATE 网络升级固件
AT+PING PING 命令

其他命令可以参考ESP8266指令手册

ESP8266 模块使用

ESP8266 WIFI 模块,实现:串口无线 AP(COM-WIFI AP)、串口无线 STA(COM-WIFI STA)和串口无线 AP+STA(COM-WIFI AP+STA)这 3 个模式的测试,每个模式又包含 TCP服务器、TCP 客户端和 UDP 这 3 个子模式。

串口无线 WIFI(COM-WIFI AP)模式,模块作为无线 WIFI 热点,允许其他 WIFI 设备连接到本模块,实现串口与其他设备之间的无线(WIFI)数据转换互传。该模式下,根据应用场景的不同,可以设置 3 个子模式:TCP 服务器、TCP 客户端,UDP。

串口无线 WIFI AP 模式,TCP 服务器配置

发送指令 作用
AT+CWMODE=2 设置模块 WIFI 模式为 AP 模式
AT+RST 重启生效
AT+CWSAP=”ESP8266”,” 12345678”,1,4 设置模块的 AP 参数:SSID 为 ESP8266,密码为12345678,通道号为 1,加密方式为:WPA_WPA2_PSK
AT+CIPMUX=1 开启多连接
AT+CIPSERVER=1,8888 开启 SERVER 模式,设置端口为 8888
AT+CIPSEND=0,25 向 ID0 发送 25 字节数据包

串口无线 WIFI AP 模式,TCP 客户端配置

发送指令 作用
AT+CWMODE=2 设置模块 WIFI 模式为 AP 模式
AT+RST 重启生效
AT+CWSAP=”ESP8266”,”12345678”,1,4 设置模块的 AP 参数:SSID 为 ESP8266,密码为12345678,通道号为 1,加密方式为:WPA_WPA2_PSK
AT+CIPMUX=0 开启单连接
AT+CIPSTART=”TCP”,”192.168.4.XXX”,8881 建立 TCP 连接到” 192.168.4.XXX”,8881
AT+CIPMODE=1 开启透传模式(仅单连接 client 时支持)
AT+CIPSEND 开始发送数据

串口无线 WIFI AP 模式,UDP 配置

发送指令 作用
AT+CWMODE=2 设置模块 WIFI 模式为 AP 模式
AT+RST 重启生效
AT+CWSAP=”ATK-ESP8266”,”AT+CWSAP=”ATK-ESP8266”,” 设置模块的 AP 参数:SSID 为 ESP8266,密码为12345678,通道号为 1,加密方式为:WPA_WPA2_PSK
AT+CIPMUX=0 开启单连接
AT+CIPSTART=”UDP”,”192.168.4.XXX”,8086 建立 UDP 连接到”192.168.4.XXX”,8086
AT+CIPSEND=25 向目标 UDP 发送 25 字节数据

串口无线 STA(COM-WIFI STA)

串口无线 STA(COM-WIFI STA)模式,模块作为无线 WIFI STA,用于连接到无线网络,实现串口与其他设备之间的无线(WIFI)数据转换互传。该模式下,根据应用场景的不同,可以设置 3 个子模式:TCP 服务器、TCP 客户端,UDP。

串口无线 STA 模式,TCP 服务器配置

发送指令 作用
AT+CWMODE=1 设置模块 WIFI 模式为 AP 模式
AT+RST 重启模块并生效
AT+CWJAP=”ESp8266”, “5201314520” 加入 WIFI 热点:SSID 为 ESp8266,密码为5201314520
AT+CIPMUX=1 开启多连接
AT+CIPSERVER=1,8888 开启 SERVER 模式,设置端口为 8888
AT+CIPSEND=0,25 向 ID0 发送 25 字节数据包

串口无线 STA 模式,TCP 客户端配置

发送指令 作用
AT+CWMODE=1 设置模块 WIFI 模式为 AP 模式
AT+RST 重启模块并生效
AT+CWJAP=”ESp8266”, “5201314520” 加入 WIFI 热点:SSID 为 ESp8266,密码为5201314520
AT+CIPMUX=0 开启单连接
AT+CIPSTART=”TCP”,”192.168.1.XXX”,8888 建立 TCP 连接到” 192.168.1.XXX”,8888
AT+CIPMODE=1 开启透传模式
AT+CIPSEND 开始传输

串口无线 STA 模式,UDP 配置

发送指令 作用
AT+CWMODE=1 设置模块 WIFI 模式为 AP 模式
AT+RST 重启模块并生效
AT+CWJAP=”ESp8266”, “5201314520” 加入 WIFI 热点:SSID 为 ESp8266,密码为5201314520
AT+CIPMUX=0 开启单连接
AT+CIPSTART=”UDP”,”192.168.1.XXX”,8888 建立 UDP 连接到” 192.168.4.XXX”,8888
AT+CIPSEND=0,25 向 ID0 发送 25 字节数据包

串口无线 AP+STA(COM-WIFI AP+STA)

串口无线 AP+STA(COM-WIFI AP+STA)模式,模块既作无线 WIFI AP,又作无线 STA,其他 WIFI 设备可以连接到该模块,模块也可以连接到其他无线网络,实现串口与其他设备之间的无线(WIFI)数据转换互传。该模式下,根据应用场景的不同,可以设置 9 个子模式:(TCP 服务器、TCP 客户端,UDP)||(TCP 服务器、TCP 客户端,UDP)

串口无线 AP+STA 模式,AP 作 TCP 服务器,STA 做 TCP 服务器的配置

发送指令 作用
AT+CWMODE=3 设置模块 WIFI 模式为 AP+STA
AT+RST 重启模块并生效
AT+CWSAP=”ESP8266”,”12345678”,1,4 加入 WIFI 热点:ESP8266,密码为:12345678
AT+CWJAP=”ESP”,”52013141314” 设置模块的 AP 参数:SSID 为 ESP,密码为52013141314,通道号为 1,加密方式为:WPA_WPA2_PSK
AT+CIPMUX=1 开启多连接
AT+CIPSERVER=1,8888 开启服务器,端口号 8888
AT+CIPSTO=1200 设置服务器超时时间 1200s
AT+CIPSEND=0,25 向 ID0 发送数据
AT+CIPSEND=1,25 向 ID1 发送数据

串口无线 AP+STA 模式,AP 作 TCP 服务器,STA 作 TCP 客户端的配置

发送指令 作用
AT+CWMODE=3 设置模块 WIFI 模式为 AP+STA
AT+RST 重启模块并生效
AT+CWSAP=”ESP8266”,”12345678”,1,4 加入 WIFI 热点:ESP8266,密码为:12345678
AT+CWJAP=”ESP”,”52013141314” 设置模块的 AP 参数:SSID 为 ESP,密码为52013141314,通道号为 1,加密方式为:WPA_WPA2_PSK
AT+CIPMUX=1 开启多连接
AT+CIPSERVER=1,8888 开启服务器,端口号 8888
AT+CIPSTO=1200 设置服务器超时时间 1200s
AT+CIPSTART=0,”TCP”,”192.168.1.XXX”,8888 STA 作为 ID0 连接到 192.168.1.XXX,8888
AT+CIPSEND=0,25 向 ID1 发送数据
AT+CIPSEND=1,25 向 ID1 发送数据

串口无线 AP+STA 模式,AP 作 TCP 服务器,STA 作 UDP 的配置

发送指令 作用
AT+CWMODE=3 设置模块 WIFI 模式为 AP+STA
AT+RST 重启模块并生效
AT+CWSAP=”ESP8266”,”12345678”,1,4 加入 WIFI 热点:ESP8266,密码为:12345678
AT+CWJAP=”ESP”,”52013141314” 设置模块的 AP 参数:SSID 为 ESP,密码为52013141314,通道号为 1,加密方式为:WPA_WPA2_PSK
AT+CIPMUX=1 开启多连接
AT+CIPSERVER=1,8888 开启服务器,端口号 8888
AT+CIPSTO=1200 设置服务器超时时间 1200s
AT+CIPSTART=0,”UDP”,”192.168.1.XXX”,8888 STA 作为 ID0 连接到 192.168.1.XXX,8888
AT+CIPSEND=0,25 向 ID1 发送数据
AT+CIPSEND=1,25 向 ID1 发送数据

Code

eps8266.c

//单片机头文件
#include "stm32f10x.h"

//网络设备驱动
#include "esp8266.h"
//硬件驱动
#include "delay.h"
#include "usart.h"
//C库
#include <string.h>
#include <stdio.h>
#define WIFI_SSID                         "spx24"                                //    WIFI的名称 必须用2.4G的wifi不能用5G的,且不能用中文、空格
#define WIFI_PSWD                         "52xiaobai999"                //    WIFI密码
#define SERVER_HOST                        "broker.emqx.io"            //    MQTT服务器域名或IP
#define SERVER_PORT                        "1883"                                //    MQTT服务器端口(一般为1883不用改)
#define ESP8266_WIFI_INFO            "AT+CWJAP=\"" WIFI_SSID "\",\"" WIFI_PSWD "\"\r\n"
#define ESP8266_ONENET_INFO        "AT+CIPSTART=\"TCP\",\"" SERVER_HOST "\"," SERVER_PORT "\r\n"
unsigned char esp8266_buf[128];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;

extern u8 ESP8266_INIT_OK;

//==========================================================
//    函数名称:    ESP8266_Clear
//
//    函数功能:    清空缓存
//
//    入口参数:    无
//
//    返回参数:    无
//
//    说明:        
//==========================================================
void ESP8266_Clear(void)
{
    memset(esp8266_buf, 0, sizeof(esp8266_buf));
    esp8266_cnt = 0;
}

//==========================================================
//    函数名称:    ESP8266_WaitRecive
//
//    函数功能:    等待接收完成
//
//    入口参数:    无
//
//    返回参数:    REV_OK-接收完成        REV_WAIT-接收超时未完成
//
//    说明:        循环调用检测是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)
{
    if(esp8266_cnt == 0)                             //如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数
        return REV_WAIT;    
    if(esp8266_cnt == esp8266_cntPre)                //如果上一次的值和这次相同,则说明接收完毕
    {
        esp8266_cnt = 0;                            //清0接收计数        
        return REV_OK;                                //返回接收完成标志
    }    
    esp8266_cntPre = esp8266_cnt;                    //置为相同
    return REV_WAIT;                                //返回接收未完成标志
}

//==========================================================
//    函数名称:    ESP8266_SendCmd
//
//    函数功能:    发送命令
//
//    入口参数:    cmd:命令
//                res:需要检查的返回指令
//
//    返回参数:    0-成功    1-失败
//
//    说明:        
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
    unsigned char timeOut = 200;
    Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));

    while(timeOut--)
    {
        if(ESP8266_WaitRecive() == REV_OK)                            //如果收到数据
        {
            if(strstr((const char *)esp8266_buf, res) != NULL)        //如果检索到关键词
            {
                ESP8266_Clear();                                    //清空缓存

                return 0;
            }
        }
        delay_ms(10);
    }
    return 1;
}

//==========================================================
//    函数名称:    ESP8266_SendData
//
//    函数功能:    发送数据
//
//    入口参数:    data:数据
//                len:长度
//
//    返回参数:    无
//
//    说明:        
//==========================================================
void ESP8266_SendData(unsigned char *data, unsigned short len)
{
    char cmdBuf[32];
    ESP8266_Clear();                                //清空接收缓存
    sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);        //发送命令
    if(!ESP8266_SendCmd(cmdBuf, ">"))                //收到‘>’时可以发送数据
    {
        Usart_SendString(USART2, data, len);        //发送设备连接请求数据
    }
}

//==========================================================
//    函数名称:    ESP8266_GetIPD
//    函数功能:    获取平台返回的数据
//    入口参数:    等待的时间(乘以10ms)
//    返回参数:    平台返回的原始数据
//    说明:        不同网络设备返回的格式不同,需要去调试
//                如ESP8266的返回格式为    "+IPD,x:yyy"    x代表数据长度,yyy是数据内容
//==========================================================
unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{
    char *ptrIPD = NULL;
    do
    {
        if(ESP8266_WaitRecive() == REV_OK)                                //如果接收完成
        {
            ptrIPD = strstr((char *)esp8266_buf, "IPD,");                //搜索“IPD”头
            if(ptrIPD == NULL)                                            //如果没找到,可能是IPD头的延迟,还是需要等待一会,但不会超过设定的时间
            {
                //DEBUG_LOG("\"IPD\" not found\r\n");
            }
            else
            {
                ptrIPD = strchr(ptrIPD, ':');                            //找到':'
                if(ptrIPD != NULL)
                {
                    ptrIPD++;
                    return (unsigned char *)(ptrIPD);
                }
                else
                    return NULL;        
            }
        }
        delay_ms(5);
        timeOut--;    //延时等待
    } while(timeOut > 0);
    return NULL;                                                        //超时还未找到,返回空指针

}

//==========================================================
//    函数名称:    ESP8266_Init
//    函数功能:    初始化ESP8266
//    入口参数:    无
//    返回参数:    无
//    说明:        
//==========================================================
void ESP8266_Init(void)
{
    ESP8266_Clear();
    DEBUG_LOG("0. AT - 测试MCU-8266通讯");
    while(ESP8266_SendCmd("AT\r\n", "OK"))
        delay_ms(500);
    DEBUG_LOG("1. AT+RST - 软复位8266");
    ESP8266_SendCmd("AT+RST\r\n", "");
        delay_ms(500);
    ESP8266_SendCmd("AT+CIPCLOSE\r\n", "");
        delay_ms(500);
    DEBUG_LOG("2. AT+CWMODE=1,1 - 设置8266工作模式为STA");
    while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))
        delay_ms(500);
    DEBUG_LOG("3. AT+CWDHCP=1,1 - 使能STA模式下DHCP");
    while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))
        delay_ms(500);
    DEBUG_LOG("4. AT+CWJAP - 连接WIFI");
    while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
        delay_ms(500);
    DEBUG_LOG("5. AT+CIPSTART - 连接服务器");
    while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
        delay_ms(500);
    ESP8266_INIT_OK = 1;
    DEBUG_LOG("6. ESP8266 Init OK - ESP8266初始化成功");
    DEBUG_LOG("ESP8266初始化            [OK]");
}

//==========================================================
//    函数名称:    USART2_IRQHandler
//
//    函数功能:    串口2收发中断
//
//    入口参数:    无
//
//    返回参数:    无
//
//    说明:        
//==========================================================
void USART2_IRQHandler(void)
{
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
    {
        if(esp8266_cnt >= sizeof(esp8266_buf))    esp8266_cnt = 0; //防止串口被刷爆
        esp8266_buf[esp8266_cnt++] = USART2->DR;
        USART_ClearFlag(USART2, USART_FLAG_RXNE);
    }

}

esp8266.h

#ifndef _ESP8266_H_
#define _ESP8266_H_
#define REV_OK        0    //接收完成标志
#define REV_WAIT    1    //接收未完成标志
void ESP8266_Init(void);
void ESP8266_Clear(void);
void ESP8266_SendData(unsigned char *data, unsigned short len);
unsigned char *ESP8266_GetIPD(unsigned short timeOut);
#endif

学习好ESP8266 可以做很多东西,例如