十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)

目录

  • 一、固件库模板
  • 二、准备资料
  • 三、简介
    • 1. 引脚
    • 2. 无线组网
      • 2.1 ESP8266 在 SoftAP 模式
      • 2.2 ESP8266 在 station 模式
      • 2.3 ESP8266 在 SoftAP + station 共存模式
    • 3、透传功能
    • 4. 基本配置(所有AT指令都必须换行)
    • 4. 模式配置
      • 4.1 STA 模式
      • 4.2 AP 模式
  • 四、实验
    • 1.硬件设计
    • 2.软件设计
      • 2.1 复制工程 (复制stm32-USART串口通讯工程)
      • 2.2 新建hc_05文件(打开工程)
      • 2.3 编写代码
        • 1. 使用串口助手和网络助手实现ESP8266通信
        • 2. 使用ESP8266 STA模式实现透传功能
          • 2.1 复制工程 (复制stm32-USART串口通讯工程)
          • 2.2 新建文件,打开工程,添加路径
          • usart.c
          • usart.h
          • esp8266.c
          • esp8266.h
          • esp8266_test.c
          • esp8266_test.h
          • main.c
        • 3. ESP8266使用Ap模式控制mcu
          • led.c
          • led.h
          • usart.c
          • esp8266_test.c
          • esp8266_test.h
          • main.c
    • 3. 编译
    • 4. 选择烧录工具并配置MDK
    • 5. 成品
      • 1. 使用MCU完成透传功能
      • 2. ESP8266使用Ap模式控制mcu
  • 工程链接

一、固件库模板

见博客:stm32f103c8t6新建固件库模板(可自取)

二、准备资料

  1. 固件库模板

  2. MDK5开发环境

  3. stm32参考手册

  4. UART串口协议

  5. stm32中断概念

  6. ESP8266模块资料

  7. 利用固件库模板点灯工程(下面第三行,手动狗头)

  8. CH340 USB→TTL模块

  9. ESP8266模块

  10. 手机软件

实验程序已经发布到百度网盘,本文末有链接可以自取

stm32参考手册

串口协议查看这篇博客USART串口协议

stm32中断概念STM32中断应用概括

ESP8266模块资料:ESP8266

串口调试工具 :https://pan.baidu.com/s/1V-jRJzb0INDXDLo9I4CJ6A 提取码:0000

网络助手(PC):https://pan.baidu.com/s/1EeDtr7eW-mIuOEZa1_4BWA 提取码:0000

网络调试助手(安卓)链接: https://pan.baidu.com/s/1uDGpyGt8VyUzcZXmWfTqhw 提取码: 0000

三、简介

十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第1张图片

ESP8266是一款超低功耗的UART-WiFi 透传模块,拥有业内极富竞争力的封装尺寸和超低能耗技术,专为移动设备和物联网应用设计,可将用户的物理设备连接到Wi-Fi 无线网络上,进行互联网或局域网通信,实现万物互联功能。

  • 支持STA/AP/STA+AP 三种工作模式
  • 内置TCP/IP协议栈,支持多路TCP Client连接
  • 支持UART/GPIO数据通信接口
  • 支持Smart Link 智能联网功能
  • 内置32位MCU,可兼作应用处理器
  • 3.3V 单电源供电
  • 支持丰富的Socket AT指令

1. 引脚

标号 PIN 引脚说明
1 3V3 模块供电正极
2 RST 低电平复位,高电平工作(默认高)
3 EN 使能端,需要进入命令模式时接3.3V
4 TX 发送端
5 RX 接收端
6 IO0 工作模式选择:悬空:FlashBoot,工作模式;下拉:UARTDownload,下载模式
7 IO2 (1)开机上电时必须为高电平,禁止硬件下拉;(2)内部默认已拉高
8 GND 模块供电负极

本模块使用USART协议,具体请看下面两个博客,这里就不继续讲解了
USART串口协议
四、stm32-USART串口通讯(重定向、接发通信、控制LED亮灭)

2. 无线组网

ESP8266 支持 softAP 模式, station 模式, softAP + station 共存模式三种。
利用 ESP8266 可以实现十分灵活的组网方式和网络拓扑。

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

2.1 ESP8266 在 SoftAP 模式

ESP8266 作为 softAP(热点),手机、 电脑、 用户设备、 其他 ESP8266 station 接口等均可以作为 station(终端用户) 连入ESP8266, 组建成一个局域网。
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第2张图片

2.2 ESP8266 在 station 模式

ESP8266 作为 station,通过路由器(AP) 连入 internet ,可向云端服务器上传、 下载数据。用户可随时使用移动终端(手机、 笔记本等) ,通过云端监控 ESP8266 模块的状况, 向 ESP8266 模块发送控制指令。

简单的来说就是ESP连接热点(可以上网),也可以手机上网,此时手机可以控制ESP8266

十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第3张图片

2.3 ESP8266 在 SoftAP + station 共存模式

ESP8266 支持 softAP+station 共存的模式,用户设备、 手机等可以作为station 连入 ESP8266 的 softAP 接口,同时, 可以控制 ESP8266 的 station接口通过路由器(AP) 连入 internet。

十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第4张图片

3、透传功能

透传, 即透明传输功能。 Host 通过 uart 将数据发给ESP8266, ESP8266 再通过无线网络将数据传出去;ESP8266 通过无线网络接收到的数据,同理通过uart 传到 Host。 ESP8266 只负责将数据传到目标地址,不对数据进行处理,发送方和接收方的数据内容、 长度完全一致,传输过程就好像透明一样。
透传需要先建立连接:

Q: 什么是透传模式?

A: 透传模式影响发送数据的方式。

如果不开启透传模式,发送数据前都必须先发送指令AT+CIPSEND=,例如:

AT+CIPSEND=4     
OK
>                //在 > 后面输入要上传的数据

开启了透传模式:

AT+CIPMODE=1	进入透传模式
AT+CIPSEND 		之后发送的所有内容将全部当成数据

退出透传模式: 发送数据"+++"就可以了。注意:此时“+++”后面,不接发送新行

注意:透传只能在单连接模式下进行,所以在建立连接之前一定要用(AT+CIPMUX=0 设置单连接)

>  AT+CIPMODE=1
>  CIPMUX and CIPSERVER must be 0

4. 基本配置(所有AT指令都必须换行)

命令 描述
基础指令
AT 测试 AT 启动
AT+RST 重启模块
AT+GMR 查看版本信息
wifi 功能指令
AT+CWMODE 选择 WIFI 应用模式
AT+CWJAP 加入 AP
AT+CWLAP 列出当前可用 AP
AT+CWQAP 退出与 AP 的连接
AT+CWSAP 设置 AP 模式下的参数
AT+ CWLIF 查看已接入设备的 IP
TCP/IP 指令
AT+CIPSTATUS 获得连接状态
AT+CIPSTART 建立 TCP 连接或注册 UDP 端口号
AT+CIPSEND 发送数据
AT+CIPCLOSE 关闭 TCP 或 UDP
AT+CIFSR 获取本地 IP 地址
AT+CIPMUX 启动多连接
AT+CIPSERVER 配置为服务器
AT+CIPMODE 设置模块传输模式
AT+CIPSTO 设置服务器超时时间
+IPD 接收到的数据

AT命令的详细说明在ESP8266这里面什么都有

4. 模式配置

4.1 STA 模式

STA 模式: ESP8266模块通过路由器连接互联网,手机或电脑通过互联网实现对设备的远程控制。

配置步骤:

 1. AT+CWMODE=1                    设置模组为STA模式。(串口助手)
 2. AT+CWLAP                 	   查询附近 WIFI(串口助手)
 3. AT+CWJAP="1202","12345678"     连接 WIFI(串口助手)
 4. AT+CIPMUX=0                    打开单连接(串口助手)
 5. AT+CIPSTART="TCP","192.168.2.6",808  (自己对应的ip地址,端口号随便,只要没有被占用都行)
 6. AT+CIPMODE=1				 使用透传模式
 7. AT+CIPSEND                    

4.2 AP 模式

AP 模式: ESP8266模块作为热点,实现手机或电脑直接与模块通信,实现局域网无线控制。

配置步骤:

1. AT+CWMODE=2
2. AT+CIPAP="192.168.4.1"
3. AT+CWSAP="ESP8266","12345678",1,0
4. AT+CIPMUX=1
5. AT+CIPSERVER=1,8888
6. AT+CIPSTO=1800
7. AT+CIFSR

四、实验

1.硬件设计

  1. ESP8266与串口通信
    GND接GND
    VCC接3.3
    RXD—CH340的TXD
    TXD—CH340的RXD
  2. 用ESP8266控制MCU
    CH340的TXD-----USART1的RX引脚相连(c8t6 的PA10)
    CH340的RXD-----USART1的TX引脚相连(c8t6 的PA9)
    ESP8266的TXD-----USART2的RX引脚相连(c8t6 的PA3)
    ESP8266的RXD-----USART2的TX引脚相连(c8t6 的PA2)

2.软件设计

  1. 使能 RX 和 TX 引脚 GPIO 时钟和 USART 时钟;

  2. 初始化 GPIO,并将 GPIO 复用到 USART 上;

  3. 配置 USART 参数;

  4. 配置中断控制器并使能 USART 接收中断;

  5. 使能 USART;

  6. 在 USART 接收中断服务函数实现数据接收和发送。

2.1 复制工程 (复制stm32-USART串口通讯工程)

四、stm32-USART串口通讯(重定向、接发通信、控制LED亮灭)

2.2 新建hc_05文件(打开工程)

十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第5张图片
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第6张图片
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第7张图片

2.3 编写代码

1. 使用串口助手和网络助手实现ESP8266通信

ESP8266的波特率为115200,8位数据位、1位停止位、无奇偶校验的通信格式。

  1. 发送AT,回复OK
    十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第8张图片

  2. AT+CWMODE=1 设置模组为STA模式。

  3. AT+CWLAP 查询附近 WIFI
    十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第9张图片

  4. AT+CWJAP=“XXX”,“XXXX” 连接 WIFI(必须为第3步能查找到的)

  5. AT+CIPMUX=0 打开单连接(否则不能透传)
    十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第10张图片

  6. AT+CIPSTART=“TCP”,“192.168.2.6”,808 (自己对应的ip地址,端口号随便,只要没有被占用都行)

  7. AT+CIPMODE=1 使用透传模式

  8. AT+CIPSEND

十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第11张图片

2. 使用ESP8266 STA模式实现透传功能

2.1 复制工程 (复制stm32-USART串口通讯工程)

四、stm32-USART串口通讯(重定向、接发通信、控制LED亮灭)

2.2 新建文件,打开工程,添加路径

十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第12张图片
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第13张图片
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第14张图片

usart.c

在USART1_IRQHandler方法下面添加 usart2的初始化和中断

struct  STRUCT_USARTx_Fram strEsp8266_Fram_Record = { 0 };
volatile uint8_t ucTcpClosedFlag = 0;

void uart2_init(u32 bound) {
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
    //USART2_TX   GPIOA.2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA2

    //USART2_RX	  GPIOA.3初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3

    //Usart2 NVIC 配置
    NVIC_PriorityGroupConfig(macNVIC_PriorityGroup_x);

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

    //USART 初始化设置

    USART_InitStructure.USART_BaudRate = bound;//串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

    USART_Init(USART2, &USART_InitStructure); //初始化串口1
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断
    USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//使能串口总线空闲中断

    USART_Cmd(USART2, ENABLE);
}

void USART2_IRQHandler(void)                	//串口1中断服务程序
{
    u8 Res;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
        Res =USART_ReceiveData(USART2);	//读取接收到的数据
        //USART_SendData(USART1,Res);
        if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )                       //预留1个字节写结束符
            strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ]  = Res;
    }

    if ( USART_GetITStatus( USART2, USART_IT_IDLE ) == SET )                                         //数据帧接收完毕
    {
        strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;
        Res = USART_ReceiveData( USART2 );
        ucTcpClosedFlag = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;

    }
}
usart.h

添加strHC05_Fram_Record结构体和uart2_init(u32 bound)函数

extern struct  STRUCT_USARTx_Fram                                  //串口数据帧的处理结构体
{
    //STRUCT_USARTx_Fram 读取的数据
    char  Data_RX_BUF [ RX_BUF_MAX_LEN ];

    union {
        __IO u16 InfAll;
        struct {
            __IO u16 FramLength       :15;                               // 14:0
            __IO u16 FramFinishFlag   :1;                                // 15
        } InfBit;
    };

}strUSART_Fram_Record,strEsp8266_Fram_Record;

//如果想串口中断接收,请不要注释以下宏定义
void uart1_init(u32 bound);
void uart2_init(u32 bound);
esp8266.c

#include "esp8266.h"
#include "delay.h"
#include 
#include 
#include 

/********************************************************************************
*
		RST --  A4
		EN  --	A5
		TX  --	A2(USART2_TX)
		RX  --	A3(USART2_RX)

********************************************************************************/


static void                   ESP8266_GPIO_Config                 ( void );



/**
  * @brief  ESP8266初始化函数
  * @param  无
  * @retval 无
  */
void ESP8266_Init ( void )
{
    ESP8266_GPIO_Config ();
    ESP8266_RST_HIGH_LEVEL();

    ESP8266_CH_DISABLE();


}


/**
  * @brief  初始化ESP8266用到的GPIO引脚
  * @param  无
  * @retval 无
  */
static void ESP8266_GPIO_Config ( void )
{
    /*定义一个GPIO_InitTypeDef类型的结构体*/
    GPIO_InitTypeDef GPIO_InitStructure;


    /* 配置 CH_PD 引脚*/
    ESP8266_CH_PD_APBxClock_FUN ( ESP8266_CH_PD_CLK, ENABLE );

    GPIO_InitStructure.GPIO_Pin = ESP8266_CH_PD_PIN;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init ( ESP8266_CH_PD_PORT, & GPIO_InitStructure );


    /* 配置 RST 引脚*/
    ESP8266_RST_APBxClock_FUN ( ESP8266_RST_CLK, ENABLE );

    GPIO_InitStructure.GPIO_Pin = ESP8266_RST_PIN;

    GPIO_Init ( ESP8266_RST_PORT, & GPIO_InitStructure );


}

/*
 * 函数名:ESP8266_Cmd
 * 描述  :对WF-ESP8266模块发送AT指令
 * 输入  :cmd,待发送的指令
 *         reply1,reply2,期待的响应,为NULL表不需响应,两者为或逻辑关系
 *         waittime,等待响应的时间
 * 返回  : 1,指令发送成功
 *         0,指令发送失败
 * 调用  :被外部调用
 */
bool ESP8266_Cmd ( char *cmd, char *reply1, char *reply2, u32 waittime )
{
    strEsp8266_Fram_Record .InfBit .FramLength = 0;               //从新开始接收新的数据包

    ESP8266_Usart ( "%s\r\n", cmd );

    if ( ( reply1 == 0 ) && ( reply2 == 0 ) )                      //不需要接收数据
        return true;

    Delay_ms ( waittime );                 //延时
    //增加一个结束符。
    strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ]  = '\0';
    //将USART2接收到的东西全部打印出来,接收到的保存在这个数组里,
    //通过串口1发送出来,这样就能看到,我们发送的指令的响应,是否出错,
    //例如:发送AT,响应是OK, ESP_USART接收到的数据是AT OK.在交给USART1发送,在PC机的串口调试助手可以看到这些信息,
    PC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF );

    strEsp8266_Fram_Record .InfBit .FramLength = 0;                             //清除接收标志
    strEsp8266_Fram_Record.InfBit.FramFinishFlag = 0;
    if ( ( reply1 != 0 ) && ( reply2 != 0 ) )
        return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) ||
                 ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );

    else if ( reply1 != 0 )
        return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) );

    else
        return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
}


/*
 * 函数名:ESP8266_Rst
 * 描述  :重启WF-ESP8266模块
 * 输入  :无
 * 返回  : 无
 * 调用  :被 ESP8266_AT_Test 调用
 */
void ESP8266_Rst ( void )
{
#if 0
    ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 );

#else
    ESP8266_RST_LOW_LEVEL();
    Delay_ms ( 500 );
    ESP8266_RST_HIGH_LEVEL();
#endif

}

/*
* 函数名:ESP8266_DHCP_CUR
* 描述  :
					:
					0:设置 ESP8266 SoftAP
					1:设置 ESP8266 Station
					2:设置 ESP8266 SoftAP 和 Station
					:
					0:关闭 DHCP
					1:开启 DHCP
* 输入  :None
* 返回  :1/0
* 调用  :ESP8266_StaTcpClient_Unvarnish_ConfigTest调用
*/
bool ESP8266_DHCP_CUR ( )
{
    char cCmd [40];
    //把格式数据写成串(函数指令)
    sprintf ( cCmd, "AT+CWDHCP_CUR=1,1");
    return ESP8266_Cmd ( cCmd, "OK", NULL, 500 );
}


bool ESP8266_AT_Test ( void )
{
    char count = 0;

    ESP8266_RST_HIGH_LEVEL();
    printf("\r\nAT测试.....\r\n");
    Delay_ms ( 2000 );
    while ( count < 10 )
    {
        printf("\r\nAT测试次数 %d......\r\n", count);
        if( ESP8266_Cmd ( "AT", "OK", NULL, 500 ) )
        {
            printf("\r\nAT测试启动成功 %d......\r\n", count);
            return 1;
        }
        ESP8266_Rst();
        ++ count;
    }
    return 0;
}

/*
* 函数名:ESP8266_Net_Mode_Choose
* 描述  :设置WF模式—ESP8266工作方式
* 输入  :None
* 返回  :状态值
* 调用  :内部调用
*/
bool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode)
{
    switch (enumMode)
    {
    //设置WiFi模式
    case STA :
        return ESP8266_Cmd("AT+CWMODE=1", "OK", "no change", 2500);
    case AP:
        return ESP8266_Cmd("AT+CWMODE=2", "OK", "no change", 2500);
    case STA_AP:
        return ESP8266_Cmd("AT+CWMODE=3", "OK", "no change", 2500);
    default:
        return false;
    }
}

/*
 * 函数名:ESP8266_JoinAP
 * 描述  :WF-ESP8266模块连接外部WiFi
 * 输入  :pSSID,WiFi名称字符串
 *       :pPassWord,WiFi密码字符串
 * 返回  : 1,连接成功
 *         0,连接失败
 * 调用  :被外部调用
 */
bool ESP8266_JoinAP(char *pSSID, char *pPassWord)
{
    char cCmd [120];
    //把格式数据写成串(函数指令)
    sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord);
    return ESP8266_Cmd ( cCmd, "OK", NULL, 1500 );
}

/*
 * 函数名:ESP8266_BuildAP
 * 描述  :WF-ESP8266模块创建WiFi热点
 * 输入  :pSSID,WiFi名称字符串
 *       :pPassWord,WiFi密码字符串
 *       :enunPsdMode,WiFi加密方式代号字符串
 * 返回  : 1,创建成功
 *         0,创建失败
 * 调用  :被外部调用
 */
bool ESP8266_BuildAP ( char * pSSID, char * pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode )
{
    char cCmd [120];

    sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", pSSID, pPassWord, enunPsdMode );

    return ESP8266_Cmd ( cCmd, "OK", 0, 1000 );

}


/*
 * 函数名:ESP8266_Enable_MultipleId
 * 描述  :WF-ESP8266模块启动多连接
 * 输入  :enumEnUnvarnishTx,配置是否多连接
 * 返回  : 1,配置成功
 *         0,配置失败
 * 调用  :被外部调用
 */
bool ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx )
{
    char cStr [20];
    //启动多连接
    sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) );
    return ESP8266_Cmd ( cStr, "OK", 0, 500 );
}


/*
 * 函数名:ESP8266_Link_Server
 * 描述  :WF-ESP8266模块连接外部服务器,
 * 输入  :enumE,网络协议
 *       :ip,服务器IP地址字符串
 *       :ComNum,服务器端口字符串
 *       :id,模块连接服务器的ID
 * 返回  : 1,连接成功
 *         0,连接失败
 * 调用  :被外部调用
 */
bool ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char *ip, char *ComNum, ENUM_ID_NO_TypeDef id)
{
    char cStr [100] = { 0 }, cCmd [120];

    switch (  enumE )
    {
    case enumTCP:
        //"TCP","iot.espressif.cn",8000
        sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum );
        break;

    case enumUDP:
        sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum );
        break;

    default:
        break;
    }
    if ( id < 5 )
        //建立TCP连接
        sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr);
    else
        sprintf ( cCmd, "AT+CIPSTART=%s", cStr );
    //如果连接已经存在,则返回ALREAY CONNECT
    return ESP8266_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );
}

/*
 * 函数名:ESP8266_StartOrShutServer
 * 描述  :WF-ESP8266模块开启或关闭服务器模式
 * 输入  :enumMode,开启/关闭
 *       :pPortNum,服务器端口号字符串
 *       :pTimeOver,服务器超时时间字符串,单位:秒
 * 返回  : 1,操作成功
 *         0,操作失败
 * 调用  :被外部调用
 */
bool ESP8266_StartOrShutServer ( FunctionalState enumMode, char *pPortNum, char *pTimeOver )
{
    char cCmd1 [120], cCmd2 [120];

    if ( enumMode )
    {
        //建立TCP服务器
        sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum );
        //设置TCP服务器超出时间
        sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver );

        return ( ESP8266_Cmd ( cCmd1, "OK", 0, 500 ) &&
                 ESP8266_Cmd ( cCmd2, "OK", 0, 500 ) );
    }

    else
    {
        sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum );

        return ESP8266_Cmd ( cCmd1, "OK", 0, 500 );
    }
}

/*
 * 函数名:ESP8266_Get_LinkStatus
 * 描述  :获取 WF-ESP8266 的连接状态,较适合单端口时使用
 * 输入  :无
 * 返回  : ESP8266 Station 接?口的状态
 *				 2: ESP8266 Station 已连接 AP,获得 IP 地址
 *         3: ESP8266 Station 已建立 TCP 或 UDP 传输
 *         4: ESP8266 Station 断开网络连接
 *         0: ESP8266 Station 获取状态失败
 * 调用  :被外部调用
 */
uint8_t ESP8266_Get_LinkStatus ( void )
{
    //查询 WF-ESP8266 的连接状态
    if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
    {
        if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) )
            return 2;

        else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) )
            return 3;

        else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) )
            return 4;
    }
    return 0;
}

/*
 * 函数名:ESP8266_Get_IdLinkStatus
 * 描述  :获取 WF-ESP8266 的端口(Id)连接状态,较适合多端口时使用
 * 输入  :无
 * 返回  : 端口(Id)的连接状态,低5位为有效位,分别对应Id5~0,某位若置1表该Id建立了连接,若被清0表该Id未建立连接
 * 调用  :被外部调用
 */
uint8_t ESP8266_Get_IdLinkStatus ( void )
{
    uint8_t ucIdLinkStatus = 0x00;

    if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
    {
        if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:0," ) )
            //给第一位置1
            ucIdLinkStatus |= 0x01;
        else
            //给第一位清0
            ucIdLinkStatus &= ~ 0x01;

        if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:1," ) )
            ucIdLinkStatus |= 0x02;
        else
            ucIdLinkStatus &= ~ 0x02;

        if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:2," ) )
            ucIdLinkStatus |= 0x04;
        else
            ucIdLinkStatus &= ~ 0x04;

        if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:3," ) )
            ucIdLinkStatus |= 0x08;
        else
            ucIdLinkStatus &= ~ 0x08;

        if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:4," ) )
            ucIdLinkStatus |= 0x10;
        else
            ucIdLinkStatus &= ~ 0x10;
    }

    return ucIdLinkStatus;
}



/*
 * 函数名:ESP8266_Inquire_ApIp
 * 描述  :获取 ESP8266 的 AP IP
 * 输入  :pApIp,存放 AP IP 的数组的首地址
 *         ucArrayLength,存放 AP IP 的数组的长度
 * 返回  : 0,获取失败
 *         1,获取成功
 * 调用  :被外部调用
 */
uint8_t ESP8266_Inquire_ApIp ( char *pApIp, uint8_t ucArrayLength )
{
    char uc;

    char *pCh;

    //查询本地 IP 地址
    ESP8266_Cmd ( "AT+CIFSR", "OK", 0, 500 );

    pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "APIP,\"" );

    if ( pCh )
        pCh += 6;

    else
        return 0;

    for ( uc = 0; uc < ucArrayLength; uc ++ )
    {
        pApIp [ uc ] = * ( pCh + uc);

        if ( pApIp [ uc ] == '\"' )
        {
            pApIp [ uc ] = '\0';
            break;
        }
    }
    return 1;

}

/*
 * 函数名:ESP8266_UnvarnishSend
 * 描述  :配置WF-ESP8266模块进入透传发送
 * 输入  :无
 * 返回  : 1,配置成功
 *         0,配置失败
 * 调用  :被外部调用
 */
bool ESP8266_UnvarnishSend ( void )
{
    //先设置传输模式,如果连接断开会不断重连,除非+++
    if ( ! ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ) )
        return false;
    //在透传模式时,开始发送数据
    return
        ESP8266_Cmd ( "AT+CIPSEND", "OK", ">", 500 );
}

/*
 * 函数名:ESP8266_ExitUnvarnishSend
 * 描述  :配置WF-ESP8266模块退出透传模式
 * 输入  :无
 * 返回  : 无
 * 调用  :被外部调用
 */
void ESP8266_ExitUnvarnishSend ( void )
{
    Delay_ms ( 1000 );
    ESP8266_Usart ( "+++" );
    Delay_ms ( 500 );
}


/*
 * 函数名:ESP8266_SendString
 * 描述  :WF-ESP8266模块发送字符串
 * 输入  :enumEnUnvarnishTx,声明是否已使能了透传模式
 *       :pStr,要发送的字符串
 *       :ulStrLength,要发送的字符串的字节数
 *       :ucId,哪个ID发送的字符串
 * 返回  : 1,发送成功
 *         0,发送失败
 * 调用  :被外部调用
 */
bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char *pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId )
{
    char cStr [20];
    bool bRet = false;

    //如果设置透传模式直接发送信息
    if ( enumEnUnvarnishTx )
    {
        ESP8266_Usart ( "%s", pStr );
        bRet = true;
    }
    else
        //先看什么连接再发送数据的长度,再发送数据
    {
        //如果是多连接需要AT+CIPSEND=,把格式数据写成串
        if ( ucId < 5 )
            sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );

        else
            sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );
        //先返回>再接收串口数据
        ESP8266_Cmd ( cStr, "> ", 0, 100 );
        //如果数据发送成功,返回:SEND	OK,否则SEND FATL
        bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 500 );
    }

    return bRet;

}

/*
 * 函数名:ESP8266_ReceiveString
 * 描述  :WF-ESP8266模块接收字符串
 * 输入  :enumEnUnvarnishTx,声明是否已使能了透传模式
 * 返回  : 接收到的字符串首地址
 * 调用  :被外部调用
 */
char *ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx )
{
    char *pRecStr = 0;

    strEsp8266_Fram_Record .InfBit .FramLength = 0;
    strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;

    while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag );
    strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';//增加一个结束符。

    if ( enumEnUnvarnishTx )
        pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;

    else
    {
        if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" ) )
            pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;
    }

    return pRecStr;

}


/*
 * 函数名:ESP8266_CWLIF
 * 描述  :查询已接入设备的IP
 * 输入  :pStaIp,存放已接入设备的IP
 * 返回  : 1,有接入设备
 *         0,无接入设备
 * 调用  :被外部调用
 */
uint8_t ESP8266_CWLIF ( char *pStaIp )
{
    uint8_t uc, ucLen;

    char *pCh, * pCh1;

    ESP8266_Cmd ( "AT+CWLIF", "OK", 0, 100 );
    pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "," );
    if ( pCh )
    {
        pCh1 = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "AT+CWLIF\r\r\n" ) + 11;
        ucLen = pCh - pCh1;
    }
    else
        return 0;
    for ( uc = 0; uc < ucLen; uc ++ )
        pStaIp [ uc ] = * ( pCh1 + uc);
    pStaIp [ ucLen ] = '\0';
    return 1;
}


/*
 * 函数名:ESP8266_CIPAP
 * 描述  :设置模块的 AP IP
 * 输入  :pApIp,模块的 AP IP
 * 返回  : 1,设置成功
 *         0,设置失败
 * 调用  :被外部调用
 */
uint8_t ESP8266_CIPAP ( char *pApIp )
{
    char cCmd [ 30 ];

    sprintf ( cCmd, "AT+CIPAP=\"%s\"", pApIp );

    if ( ESP8266_Cmd ( cCmd, "OK", 0, 5000 ) )
        return 1;

    else
        return 0;
}


/*
 * 函数名:ESP8266_CIPAP
 * 描述  :设置模块的 AP IP
 * 输入  :pApIp,模块的 AP IP
 * 返回  : 1,设置成功
 *         0,设置失败
 * 调用  :被外部调用
 */
uint8_t ESP8266_CIPSTA ( char *pStaIp )
{
    char cCmd [ 30 ];

    sprintf ( cCmd, "AT+CIPSTA=\"%s\"", pStaIp );

    if ( ESP8266_Cmd ( cCmd, "OK", 0, 5000 ) )
        return 1;

    else
        return 0;

}

esp8266.h


#ifndef __ESP8266_H_
#define __ESP8266_H_

#include "stm32f10x.h"
#include "sys.h"
#include "usart.h"
#include 
#include 



/******************************* ESP8266 数据类型定义 ***************************/
//工作模式
typedef enum
{
    STA,
    AP,
    STA_AP
} ENUM_Net_ModeTypeDef;

//网络协议
typedef enum
{
    enumTCP,
    enumUDP,
} ENUM_NetPro_TypeDef;

//模块连接服务器的ID
typedef enum
{
    Multiple_ID_0 = 0,
    Multiple_ID_1 = 1,
    Multiple_ID_2 = 2,
    Multiple_ID_3 = 3,
    Multiple_ID_4 = 4,
    Single_ID_0 = 5,
} ENUM_ID_NO_TypeDef;

//
typedef enum
{
    OPEN = 0,
    WEP = 1,
    WPA_PSK = 2,
    WPA2_PSK = 3,
    WPA_WPA2_PSK = 4,
} ENUM_AP_PsdMode_TypeDef;

/******************************** ESP8266 连接引脚定义 ***********************************/
#define      ESP8266_CH_PD_APBxClock_FUN                   RCC_APB2PeriphClockCmd
#define      ESP8266_CH_PD_CLK                             RCC_APB2Periph_GPIOB
#define      ESP8266_CH_PD_PORT                            GPIOB
#define      ESP8266_CH_PD_PIN                             GPIO_Pin_8

#define      ESP8266_RST_APBxClock_FUN                     RCC_APB2PeriphClockCmd
#define      ESP8266_RST_CLK                               RCC_APB2Periph_GPIOB
#define      ESP8266_RST_PORT                              GPIOB
#define      ESP8266_RST_PIN                               GPIO_Pin_9

#define      ESP8266_USARTx                                 USART2
#define      DEBUG_USARTx                         	        USART1

/******************************* ESP8266 外部全局变量声明 *******************123********/



/*********************************************** ESP8266 函数宏定义 *******************************************/
#define     ESP8266_Usart( fmt, ... )           USART_printf ( ESP8266_USARTx, fmt, ##__VA_ARGS__ )
#define     PC_Usart( fmt, ... )                printf ( fmt, ##__VA_ARGS__ )
//#define     macPC_Usart( fmt, ... )

#define     ESP8266_CH_ENABLE()                 GPIO_SetBits ( ESP8266_CH_PD_PORT, ESP8266_CH_PD_PIN )
#define     ESP8266_CH_DISABLE()                GPIO_ResetBits ( ESP8266_CH_PD_PORT, ESP8266_CH_PD_PIN )

#define     ESP8266_RST_HIGH_LEVEL()            GPIO_SetBits ( ESP8266_RST_PORT, ESP8266_RST_PIN )
#define     ESP8266_RST_LOW_LEVEL()             GPIO_ResetBits ( ESP8266_RST_PORT, ESP8266_RST_PIN )


/******************************** ESP8266 函数声明  *********************************/
void                     ESP8266_Init                        ( void );
void                     ESP8266_Rst                         ( void );
bool                     ESP8266_Cmd                         ( char *cmd, char *reply1, char *reply2, u32 waittime );
bool                     ESP8266_AT_Test                     ( void );
bool                     ESP8266_Net_Mode_Choose             ( ENUM_Net_ModeTypeDef enumMode );
bool                     ESP8266_JoinAP                      ( char *pSSID, char *pPassWord );
bool                     ESP8266_BuildAP                     ( char *pSSID, char *pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode );
bool                     ESP8266_Enable_MultipleId           ( FunctionalState enumEnUnvarnishTx );
bool                     ESP8266_Link_Server                 ( ENUM_NetPro_TypeDef enumE, char *ip, char *ComNum, ENUM_ID_NO_TypeDef id);
bool                     ESP8266_StartOrShutServer           ( FunctionalState enumMode, char *pPortNum, char *pTimeOver );
uint8_t                  ESP8266_Get_LinkStatus              ( void );
uint8_t                  ESP8266_Get_IdLinkStatus            ( void );
uint8_t                  ESP8266_Inquire_ApIp                ( char *pApIp, uint8_t ucArrayLength );
bool                     ESP8266_UnvarnishSend               ( void );
void                     ESP8266_ExitUnvarnishSend           ( void );
bool                     ESP8266_SendString                  ( FunctionalState enumEnUnvarnishTx, char *pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId );
char                    *ESP8266_ReceiveString               ( FunctionalState enumEnUnvarnishTx );
bool                     ESP8266_DHCP_CUR                    ( void );


uint8_t                  ESP8266_CWLIF                       ( char * pStaIp );
uint8_t                  ESP8266_CIPAP                       ( char * pApIp );
uint8_t                  ESP8266_CIPSTA                      ( char * pStaIp );  // new

//void ESP8266_AT_Test ( void );
#endif

esp8266_test.c

#include "esp8266_test.h"
#include "esp8266.h"
#include 
#include "led.h"
#include 
#include 



//volatile uint8_t ucTcpClosedFlag = 0;
bool ESP8266_AT_Test ( void );


/**
  * @brief  ESP8266 StaTcpClient Unvarnish 配置测试函数
  * @param  无
  * @retval 无
  */
void ESP8266_StaTcpClient_Unvarnish_ConfigTest(void)
{
    printf( "\r\n正在配置 ESP8266 ......\r\n" );
    printf( "\r\n使能 ESP8266 ......\r\n" );
    ESP8266_CH_ENABLE();
    while( ! ESP8266_AT_Test() );
    while( ! ESP8266_DHCP_CUR () );
    printf( "\r\n正在配置工作模式 STA ......\r\n" );
    while( ! ESP8266_Net_Mode_Choose ( STA ) );

    printf( "\r\n正在连接 WiFi ......\r\n" );
    while( ! ESP8266_JoinAP ( User_ESP8266_ApSsid, User_ESP8266_ApPwd ) );

    printf( "\r\n禁止多连接 ......\r\n" );
    while( ! ESP8266_Enable_MultipleId ( DISABLE ) );

    printf( "\r\n正在连接 Server ......\r\n" );
    while( !	ESP8266_Link_Server ( enumTCP, User_ESP8266_TcpServer_IP, User_ESP8266_TcpServer_Port, Single_ID_0 ) );

    printf( "\r\n进入透传发送模式 ......\r\n" );
    while( ! ESP8266_UnvarnishSend () );

    printf( "\r\n配置 ESP8266 完毕\r\n" );
    printf ( "\r\n开始透传......\r\n" );

}


/**
  * @brief  ESP8266 检查是否接收到了数据,检查连接和掉线重连
  * @param  无
  * @retval 无
  */
void ESP8266_CheckRecvDataTest(void)
{
    uint8_t ucStatus;
    uint16_t i;

    /* 如果接收到了串口调试助手的数据 */
    if(strUSART_Fram_Record.InfBit.FramFinishFlag == 1)
    {
        for(i = 0; i < strUSART_Fram_Record.InfBit.FramLength; i++)
        {
            USART_SendData( ESP8266_USARTx,strUSART_Fram_Record.Data_RX_BUF[i]);  //转发给ESP82636
            while(USART_GetFlagStatus(ESP8266_USARTx,USART_FLAG_TC)==RESET) {}     //等待发送完成
        }
        strUSART_Fram_Record .InfBit .FramLength = 0;                                //接收数据长度置零
        strUSART_Fram_Record .InfBit .FramFinishFlag = 0;                            //接收标志置零
    }

    /* 如果接收到了ESP8266的数据 */
    if(strEsp8266_Fram_Record.InfBit.FramFinishFlag)
    {
        for(i = 0; i < strEsp8266_Fram_Record .InfBit .FramLength; i++)
        {
            USART_SendData( DEBUG_USARTx,strEsp8266_Fram_Record .Data_RX_BUF[i]);     //转发给ESP82636
            while(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TC)==RESET) {}
        }
        strEsp8266_Fram_Record .InfBit .FramLength = 0;                             //接收数据长度置零
        strEsp8266_Fram_Record.InfBit.FramFinishFlag = 0;                           //接收标志置零
    }

    if ( ucTcpClosedFlag )                                             //检测是否失去连接
    {
        ESP8266_ExitUnvarnishSend ();                                    //退出透传模式

        do ucStatus = ESP8266_Get_LinkStatus ();                         //获取连接状态
        while ( ! ucStatus );

        if ( ucStatus == 4 )                                             //确认失去连接后重连
        {
            printf ( "\r\n正在重连热点和服务器 ......\r\n" );

            while ( ! ESP8266_JoinAP ( User_ESP8266_ApSsid, User_ESP8266_ApPwd ) );

            while ( !	ESP8266_Link_Server ( enumTCP, User_ESP8266_TcpServer_IP, User_ESP8266_TcpServer_Port, Single_ID_0 ) );

            printf ( "\r\n重连热点和服务器成功\r\n" );

        }

        while ( ! ESP8266_UnvarnishSend () );

    }
}

esp8266_test.h
#ifndef  __ESP8266_TEST_H
#define	 __ESP8266_TEST_H



#include "stm32f10x.h"



/********************************** 用户需要设置的参数**********************************/
#define      User_ESP8266_ApSsid                       "ChinaNet-057B"                //要连接的热点的名称
#define      User_ESP8266_ApPwd                        "abc1314520"           //要连接的热点的密钥

#define      User_ESP8266_TcpServer_IP                 "192.168.2.6"      //要连接的服务器的 IP
#define      User_ESP8266_TcpServer_Port               "808"               //要连接的服务器的端口



/********************************** 外部全局变量 ***************************************/
extern volatile uint8_t ucTcpClosedFlag;
extern int read_dht11_finish;


/********************************** 测试函数声明 ***************************************/
void ESP8266_StaTcpClient_Unvarnish_ConfigTest(void);
void ESP8266_CheckRecvDataTest(void);
#endif

main.c
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "esp8266.h"
#include "esp8266_test.h"
#include "stm32f10x.h"
#include "stdio.h"


int main()
{
	
    uart1_init(115200);	 	//串口初始化为115200
    uart2_init(115200);	 	//串口初始化为115200
    /* 初始化 */
    LED_GPIO_Config();
    ESP8266_Init ();

    ESP8266_StaTcpClient_Unvarnish_ConfigTest();                          //对ESP8266进行配置
    while(1)
    {
			ESP8266_CheckRecvDataTest();
    }
}

3. ESP8266使用Ap模式控制mcu

stm32f103c8t6自带一个led灯,使用PC13引脚就行了,

切记尽量避免使用PB3、PB4,具体看stm32f103c8t6使用PB3和PB4做普通GPIO使用时发现异常

led.c
#include "led.h"	//绑定led.h

void LED_GPIO_Config(void) {
    GPIO_InitTypeDef GPIO_InitStruct; //初始化参数结构体指针,结构体类型为 GPIO_InitTypeDef。
    //开启RCC时钟
    RCC_APB2PeriphClockCmd(LED_G_GPIO_CLK, ENABLE);

    //配置初始化,推挽输出方式和LED_G_GPIO_PIN管脚、赫兹
    GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    //GPIO口初始化
    GPIO_Init(LED_G_GPIO_PORT, &GPIO_InitStruct);
}

led.h
#ifndef __LED_H_
#define __LED_H_

#include "stm32f10x.h"
#include "sys.h"

#define LED_G_GPIO_PIN         GPIO_Pin_13
#define LED_G_GPIO_PORT        GPIOC
#define LED_G_GPIO_CLK         RCC_APB2Periph_GPIOC
//使用位带操作来实现操作某个IO口的 1个位,由sys.h实现
#define LED 				   PCout(13)

void LED_GPIO_Config(void); //函数定义

#endif
usart.c

usart.c 、usart.h 、esp8266.c、esp8266.h等文件和实现穿透的代码一样,

esp8266_test.c

#include "esp8266_test.h"
#include "esp8266.h"
#include 
#include "led.h"
#include "delay.h"
#include 
#include 


uint8_t ucId, ucLen;
uint8_t ucLed1Status = 0;
char cStr [ 100 ] = { 0 }, cCh;
char *pCh, * pCh1;


//volatile uint8_t ucTcpClosedFlag = 0;
bool ESP8266_AT_Test ( void );



/**
  * @brief  ESP8266 ApTcpServer 配置测试函数
  * @param  无
  * @retval 无
  */
void ESP8266_ApTcpServer_ConfigTest(void)
{
    printf( "\r\n正在配置 ESP8266 ......\r\n" );
    printf( "\r\n使能 ESP8266 ......\r\n" );
    ESP8266_CH_ENABLE();
    while( ! ESP8266_AT_Test() );

    printf( "\r\n正在配置工作模式为 AP ......\r\n" );
    while( ! ESP8266_Net_Mode_Choose ( AP ) );

    printf( "\r\n正在创建WiFi热点 ......\r\n" );
    while ( ! ESP8266_CIPAP ( User_ESP8266_TcpServer_IP ) ); //设置模块的 AP IP
    while ( ! ESP8266_BuildAP ( User_ESP8266_BulitApSsid, User_ESP8266_BulitApPwd, User_ESP8266_BulitApEcn ) );

    printf( "\r\n允许多连接 ......\r\n" );
    while( ! ESP8266_Enable_MultipleId ( ENABLE ) );

    printf( "\r\n开启服务器模式 ......\r\n" );
    while ( !	ESP8266_StartOrShutServer ( ENABLE, User_ESP8266_TcpServer_Port, User_ESP8266_TcpServer_OverTime ) );


    ESP8266_Inquire_ApIp ( cStr, 20 );
    printf ( "\n本模块WIFI为 %s,密码开放\nAP IP 为:%s,开启的端口为:%s\r\n手机网络助手连接该 IP 和端口,最多可连接5个客户端\n",
             User_ESP8266_BulitApSsid, cStr, User_ESP8266_TcpServer_Port );


    strEsp8266_Fram_Record .InfBit .FramLength = 0;
    strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;

    printf( "\r\n配置 ESP8266 完毕\r\n" );

}

/**
  * @brief  ESP8266 检查接收信息并发送数据测试函数
  * @param  无
  * @retval 无
  */
void ESP8266_CheckRecvDataTest(void)
{
    if ( strEsp8266_Fram_Record .InfBit .FramFinishFlag )					//如果有数据传输结束
    {
        USART_ITConfig ( ESP8266_USARTx, USART_IT_RXNE, DISABLE ); //禁用串口接收中断,防止影响

        strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ]  = '\0';
        printf("ucCh =%s\n", strEsp8266_Fram_Record .Data_RX_BUF);
        if(strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "LED=1" ))	//如果手机发送的数据存在LED=1,则if成立
        {
            PCout(13) = 1; //PC口13引脚输出,高电平
            printf("\r\nLED灭\r\n");
            Delay_ms(500);		//已经在delay.h中初始化

        }
        else	if(strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "LED=0" ))
        {
            PCout(13) = 0; //PC口13引脚输出,低电平
            printf("\r\nLED亮\r\n");
            Delay_ms(500);

        }

        if ( ( pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD," ) ) != 0 )
        {
            ucId = * ( pCh + strlen ( "+IPD," ) ) - '0';
            ESP8266_SendString ( DISABLE, cStr, strlen ( cStr ), ( ENUM_ID_NO_TypeDef ) ucId );
        }

        strEsp8266_Fram_Record .InfBit .FramLength = 0;
        strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;

        USART_ITConfig ( ESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中断
    }
}

esp8266_test.h
#ifndef  __ESP8266_TEST_H
#define	 __ESP8266_TEST_H



#include "stm32f10x.h"



/********************************** 用户需要设置的参数**********************************/
#define      User_ESP8266_ApSsid                       "ChinaNet-057B"                //要连接的热点的名称
#define      User_ESP8266_ApPwd                        "abc1314520"           //要连接的热点的密钥

#define      User_ESP8266_TcpServer_IP                 "192.168.4.1"      //要连接的服务器的 IP
#define      User_ESP8266_TcpServer_Port               "8888"               //要连接的服务器的端口


#define   	 User_ESP8266_BulitApSsid         "ESP8266"      //要建立的热点的名称
#define   	 User_ESP8266_BulitApEcn           OPEN               //要建立的热点的加密方式
#define   	 User_ESP8266_BulitApPwd           "12345678"         //要建立的热点的密钥

#define      User_ESP8266_TcpServer_OverTime   "1800"             //服务器超时时间(单位:秒)


/********************************** 外部全局变量 ***************************************/
extern volatile uint8_t ucTcpClosedFlag;
extern int read_dht11_finish;


/********************************** 测试函数声明 ***************************************/
void ESP8266_ApTcpServer_ConfigTest(void);
void ESP8266_CheckRecvDataTest(void);
#endif


main.c

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "esp8266.h"
#include "esp8266_test.h"
#include "stm32f10x.h"
#include "stdio.h"


int main()
{
	
    uart1_init(115200);	 	//串口初始化为115200
    uart2_init(115200);	 	//串口初始化为115200
    /* 初始化 */
    LED_GPIO_Config();
    ESP8266_Init ();

    ESP8266_ApTcpServer_ConfigTest();                          //对ESP8266进行配置
    while(1)
    {
			ESP8266_CheckRecvDataTest();
    }
}

3. 编译

编译成功
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第15张图片

4. 选择烧录工具并配置MDK

本文选择的是ST_Link烧录工具
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第16张图片
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第17张图片
如果没有ID号看博客:ST-Link V2烧录问题(已解决)
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第18张图片
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第19张图片

5. 成品

1. 使用MCU完成透传功能

十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第20张图片

2. ESP8266使用Ap模式控制mcu

十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第21张图片
十、stm32-ESP8266(串口透传、MCU透传、控制LED亮灭)_第22张图片
这个工具开头已经提供

这里PC13已经亮灭了就没有上传截图,大家自己可以试试

工程链接

使用MCU完成透传功能:
链接:https://pan.baidu.com/s/1RugvDofb_JQDTqpoYFQ-8w 提取码:0000
ESP8266使用Ap模式控制mcu:
链接:https://pan.baidu.com/s/1Fol88R_HwS9LNbLXYpN5Iw 提取码:0000

你可能感兴趣的:(stm32,单片机,mcu)