STM32封装ESP8266一键配置函数:实现实现AP模式和STA模式切换、服务器与客户端创建

简介: STM32封装ESP8266一键配置函数:实现实现AP模式和STA模式切换、服务器与客户端创建

工程源码下载: https://download.csdn.net/download/xiaolong1126626497/15805037

一、硬件环境介绍

1.  ESP8266 :采用安信可的模组,型号是ESP12F

image.png

2.  STM32     :  采用STM32F103C8T6


3.  编程软件  :  采用Keil5


ESP8266编程调试过程中用到的相关软件下载地址:


物联网网调试终端:https://download.csdn.net/download/xiaolong1126626497/12624530

image.png

image.png

TCP调试助手:https://download.csdn.net/download/xiaolong1126626497/12624461

image.png

串口调试助手:https://download.csdn.net/download/xiaolong1126626497/12624450

image.png

二、ESP8266通信的调试与运行效果

下面几张图是将ESP8266配置成AP+TCP服务器模式,电脑连接ESP8266的热点之后,实现数据通信。通信的效果是,在电脑点击物联网控制系统软件,实现控制开发板上的LED灯和蜂鸣器,开发板上将检测的光敏数据、温度数据、RC522刷卡数据传输到电脑的软件上进行显示。----局域网通信

image.png

image.png

image.png

三、硬件接线与代码技术部分介绍

硬件连接: 下面会贴出核心代码,在当前开发板上,ESP8266接在STM32F103C8T6的串口3上。


代码分为以下几个部分:


(1) STM32程序里的串口接收采用定时器+接收中断的形式接收数据,使用这种方式可以接收不定长度数据,方便接下来与ESP8266进行通信。


(2). ESP8266驱动代码:代码实现了STA+TCP客户端的一键配置函数,AP+TCP服务器的一键配置函数,要配置ESP8266只需要调用对应的函数传入参数即可。


四、核心代码部分

4.1 ESP8266.c代码

#include "esp8266.h"
u8 ESP8266_IP_ADDR[16]; //255.255.255.255
u8 ESP8266_MAC_ADDR[18]; //硬件地址
/*
函数功能: ESP8266命令发送函数
函数返回值:0表示成功  1表示失败
*/
u8 ESP8266_SendCmd(char *cmd)
{
    u8 i,j;
    for(i=0;i<10;i++) //检测的次数--发送指令的次数
    {
        USARTx_StringSend(USART3,cmd);
        for(j=0;j<100;j++) //等待的时间
        {
            delay_ms(50);
            if(USART3_RX_FLAG)
            {
                USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                USART3_RX_FLAG=0;
                USART3_RX_CNT=0;
                if(strstr((char*)USART3_RX_BUFFER,"OK"))
                {
                    return 0;
                }
            }
        }
    }
    return 1;
}
/*
函数功能: ESP8266硬件初始化检测函数
函数返回值:0表示成功  1表示失败
*/
u8 ESP8266_Init(void)
{
    //退出透传模式
    USARTx_StringSend(USART3,"+++");
    delay_ms(50);
    return ESP8266_SendCmd("AT\r\n");
}
/*
函数功能: 一键配置WIFI为AP+TCP服务器模式
函数参数:
char *ssid  创建的热点名称
char *pass  创建的热点密码 (最少8位)
u16 port    创建的服务器端口号
函数返回值: 0表示成功 其他值表示对应错误值
*/
u8 ESP8266_AP_TCP_Server_Mode(char *ssid,char *pass,u16 port)
{
    char *p;
    u8 i;
    char ESP8266_SendCMD[100]; //组合发送过程中的命令
    /*1. 测试硬件*/
    if(ESP8266_SendCmd("AT\r\n"))return 1;
    /*2. 关闭回显*/
    if(ESP8266_SendCmd("ATE0\r\n"))return 2;
    /*3. 设置WIFI模式*/
    if(ESP8266_SendCmd("AT+CWMODE=2\r\n"))return 3;
    /*4. 复位*/
    ESP8266_SendCmd("AT+RST\r\n");
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    /*5. 关闭回显*/
    if(ESP8266_SendCmd("ATE0\r\n"))return 5;
    /*6. 设置WIFI的AP模式参数*/
    sprintf(ESP8266_SendCMD,"AT+CWSAP=\"%s\",\"%s\",1,4\r\n",ssid,pass);
    if(ESP8266_SendCmd(ESP8266_SendCMD))return 6;
    /*7. 开启多连接*/
    if(ESP8266_SendCmd("AT+CIPMUX=1\r\n"))return 7;
    /*8. 设置服务器端口号*/
    sprintf(ESP8266_SendCMD,"AT+CIPSERVER=1,%d\r\n",port);
    if(ESP8266_SendCmd(ESP8266_SendCMD))return 8;
    /*9. 查询本地IP地址*/
    if(ESP8266_SendCmd("AT+CIFSR\r\n"))return 9;
    //提取IP地址
    p=strstr((char*)USART3_RX_BUFFER,"APIP");
    if(p)
    {
        p+=6;
        for(i=0;*p!='"';i++)
        {
            ESP8266_IP_ADDR[i]=*p++;
        }
        ESP8266_IP_ADDR[i]='\0';
    }
    //提取MAC地址
    p=strstr((char*)USART3_RX_BUFFER,"APMAC");
    if(p)
    {
        p+=7;
        for(i=0;*p!='"';i++)
        {
            ESP8266_MAC_ADDR[i]=*p++;
        }
        ESP8266_MAC_ADDR[i]='\0';
    }
    //打印总体信息
    USART1_Printf("当前WIFI模式:AP+TCP服务器\n");
    USART1_Printf("当前WIFI热点名称:%s\n",ssid);
    USART1_Printf("当前WIFI热点密码:%s\n",pass);
    USART1_Printf("当前TCP服务器端口号:%d\n",port);
    USART1_Printf("当前TCP服务器IP地址:%s\n",ESP8266_IP_ADDR);
    USART1_Printf("当前TCP服务器MAC地址:%s\n",ESP8266_MAC_ADDR);
    return 0;
}
/*
函数功能: TCP服务器模式下的发送函数
发送指令: 
*/
u8 ESP8266_ServerSendData(u8 id,u8 *data,u16 len)
{
    u8 i,j,n;
    char ESP8266_SendCMD[100]; //组合发送过程中的命令
    for(i=0;i<10;i++)
    {
        sprintf(ESP8266_SendCMD,"AT+CIPSEND=%d,%d\r\n",id,len);
        USARTx_StringSend(USART3,ESP8266_SendCMD);
        for(j=0;j<10;j++)
        {
            delay_ms(50);
            if(USART3_RX_FLAG)
            {
                USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                USART3_RX_FLAG=0;
                USART3_RX_CNT=0;
                if(strstr((char*)USART3_RX_BUFFER,">"))
                {
                    //继续发送数据
                    USARTx_DataSend(USART3,data,len);
                    //等待数据发送成功
                    for(n=0;n<200;n++)
                    {
                        delay_ms(50);
                        if(USART3_RX_FLAG)
                        {
                            USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                            USART3_RX_FLAG=0;
                            USART3_RX_CNT=0;
                            if(strstr((char*)USART3_RX_BUFFER,"SEND OK"))
                            {
                                return 0;
                            }
                         }            
                    }   
                }
            }
        }
    }
    return 1;
}
/*
函数功能: 配置WIFI为STA模式+TCP客户端模式
函数参数:
char *ssid  创建的热点名称
char *pass  创建的热点密码 (最少8位)
char *p     将要连接的服务器IP地址
u16 port    将要连接的服务器端口号
u8 flag     1表示开启透传模式 0表示关闭透传模式
函数返回值:0表示成功  其他值表示对应的错误
*/
u8 ESP8266_STA_TCP_Client_Mode(char *ssid,char *pass,char *ip,u16 port,u8 flag)
{
    char ESP8266_SendCMD[100]; //组合发送过程中的命令
    //退出透传模式
    //USARTx_StringSend(USART3,"+++");
    //delay_ms(50);
    /*1. 测试硬件*/
    if(ESP8266_SendCmd("AT\r\n"))return 1;
    /*2. 关闭回显*/
    if(ESP8266_SendCmd("ATE0\r\n"))return 2;
    /*3. 设置WIFI模式*/
    if(ESP8266_SendCmd("AT+CWMODE=1\r\n"))return 3;
    /*4. 复位*/
    ESP8266_SendCmd("AT+RST\r\n");
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    /*5. 关闭回显*/
    if(ESP8266_SendCmd("ATE0\r\n"))return 5;
    /*6. 配置将要连接的WIFI热点信息*/
    sprintf(ESP8266_SendCMD,"AT+CWJAP=\"%s\",\"%s\"\r\n",ssid,pass);
    if(ESP8266_SendCmd(ESP8266_SendCMD))return 6;
    /*7. 设置单连接*/
    if(ESP8266_SendCmd("AT+CIPMUX=0\r\n"))return 7;
    /*8. 配置要连接的TCP服务器信息*/
    sprintf(ESP8266_SendCMD,"AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",ip,port);
    if(ESP8266_SendCmd(ESP8266_SendCMD))return 8;
    /*9. 开启透传模式*/
    if(flag)
    {
       if(ESP8266_SendCmd("AT+CIPMODE=1\r\n"))return 9; //开启
       if(ESP8266_SendCmd("AT+CIPSEND\r\n"))return 10;  //开始透传
       if(!(strstr((char*)USART3_RX_BUFFER,">")))
       {
            return 11;
       }
        //如果想要退出发送:  "+++"
    }
     //打印总体信息
    USART1_Printf("当前WIFI模式:STA+TCP客户端\n");
    USART1_Printf("当前连接的WIFI热点名称:%s\n",ssid);
    USART1_Printf("当前连接的WIFI热点密码:%s\n",pass);
    USART1_Printf("当前连接的TCP服务器端口号:%d\n",port);
    USART1_Printf("当前连接的TCP服务器IP地址:%s\n",ip);
    return 0;
}
/*
函数功能: TCP客户端模式下的发送函数
发送指令: 
*/
u8 ESP8266_ClientSendData(u8 *data,u16 len)
{
    u8 i,j,n;
    char ESP8266_SendCMD[100]; //组合发送过程中的命令
    for(i=0;i<10;i++)
    {
        sprintf(ESP8266_SendCMD,"AT+CIPSEND=%d\r\n",len);
        USARTx_StringSend(USART3,ESP8266_SendCMD);
        for(j=0;j<10;j++)
        {
            delay_ms(50);
            if(USART3_RX_FLAG)
            {
                USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                USART3_RX_FLAG=0;
                USART3_RX_CNT=0;
                if(strstr((char*)USART3_RX_BUFFER,">"))
                {
                    //继续发送数据
                    USARTx_DataSend(USART3,data,len);
                    //等待数据发送成功
                    for(n=0;n<200;n++)
                    {
                        delay_ms(50);
                        if(USART3_RX_FLAG)
                        {
                            USART3_RX_BUFFER[USART3_RX_CNT]='\0';
                            USART3_RX_FLAG=0;
                            USART3_RX_CNT=0;
                            if(strstr((char*)USART3_RX_BUFFER,"SEND OK"))
                            {
                                return 0;
                            }
                         }            
                    }   
                }
            }
        }
    }
    return 1;
}

4.2 ESP8266.h

#ifndef _ESP8266_H
#define _ESP8266_H
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
//函数声明
u8 ESP8266_Init(void);
u8 ESP8266_SendCmd(char *cmd);
u8 ESP8266_AP_TCP_Server_Mode(char *ssid,char *pass,u16 port);
u8 ESP8266_ServerSendData(u8 id,u8 *data,u16 len);
u8 ESP8266_STA_TCP_Client_Mode(char *ssid,char *pass,char *ip,u16 port,u8 flag);
u8 ESP8266_ClientSendData(u8 *data,u16 len);
#endif

4.3 串口部分代码

/*
函数功能: 串口1的初始化
硬件连接: PA9(TX)  和 PA10(RX)
*/
void USART1_Init(u32 baud)
{
    /*1. 开时钟*/
    RCC->APB2ENR|=1<<14; //USART1时钟
    RCC->APB2ENR|=1<<2;  //PA
    RCC->APB2RSTR|=1<<14; //开启复位时钟
    RCC->APB2RSTR&=~(1<<14);//停止复位
    /*2. 配置GPIO口的模式*/
    GPIOA->CRH&=0xFFFFF00F;
    GPIOA->CRH|=0x000008B0;
    /*3. 配置波特率*/
    USART1->BRR=72000000/baud;
    /*4. 配置核心寄存器*/
    USART1->CR1|=1<<5; //开启接收中断
    STM32_SetPriority(USART1_IRQn,1,1); //设置中断优先级
    USART1->CR1|=1<<2; //开启接收
    USART1->CR1|=1<<3; //开启发送
    USART1->CR1|=1<<13;//开启串口功能
}
/*
函数功能: 串口3的初始化
硬件连接: PB10(TX)  和 PB11(RX)
*/
void USART3_Init(u32 baud)
{
    /*1. 开时钟*/
    RCC->APB1ENR|=1<<18; //USART3时钟
    RCC->APB2ENR|=1<<3;  //PB
    RCC->APB1RSTR|=1<<18; //开启复位时钟
    RCC->APB1RSTR&=~(1<<18);//停止复位
    /*2. 配置GPIO口的模式*/
    GPIOB->CRH&=0xFFFF00FF;
    GPIOB->CRH|=0x00008B00;
    /*3. 配置波特率*/
    USART3->BRR=36000000/baud;
    /*4. 配置核心寄存器*/
    USART3->CR1|=1<<5; //开启接收中断
    STM32_SetPriority(USART3_IRQn,1,1); //设置中断优先级
    USART3->CR1|=1<<2; //开启接收
    USART3->CR1|=1<<3; //开启发送
    USART3->CR1|=1<<13;//开启串口功能
}
u8 USART3_RX_BUFFER[USART3_RX_LENGTH]; //保存接收数据的缓冲区
u32 USART3_RX_CNT=0;  //当前接收到的数据长度
u8 USART3_RX_FLAG=0; //1表示数据接收完毕 0表示没有接收完毕
//串口3的中断服务函数
void USART3_IRQHandler(void)
{
    u8 data;
    //接收中断
    if(USART3->SR&1<<5)
    {
        TIM3->CNT=0; //清除计数器
        TIM3->CR1|=1<<0; //开启定时器3
        data=USART3->DR; //读取串口数据
      //  if(USART3_RX_FLAG==0) //判断上一次的数据是否已经处理完毕
        {
            //判断是否可以继续接收
            if(USART3_RX_CNT<USART3_RX_LENGTH)
            {
               USART3_RX_BUFFER[USART3_RX_CNT++]=data;
            }
            else  //不能接收,超出存储范围,强制表示接收完毕
            {
                USART3_RX_FLAG=1;
            }
        } 
    }
}
/*
函数功能: 字符串发送
*/
void USARTx_StringSend(USART_TypeDef *USARTx,char *str)
{
   while(*str!='\0')
   {
       USARTx->DR=*str++;
       while(!(USARTx->SR&1<<7)){}
   }
}
/*
函数功能: 数据发送
*/
void USARTx_DataSend(USART_TypeDef *USARTx,u8 *data,u32 len)
{
   u32 i;
   for(i=0;i<len;i++)
   {
       USARTx->DR=*data++;
       while(!(USARTx->SR&1<<7)){}
   }
}
/*
函数功能: 格式化打印函数
*/
char USART1_PRINTF_BUFF[1024];
void USART1_Printf(char *fmt,...)
{
   va_list ap;
   /*1. 初始化形参列表*/
   va_start(ap,fmt);
   /*2. 提取可变形参数据*/
    vsprintf(USART1_PRINTF_BUFF,fmt,ap);
   /*3. 结束,释放空间*/
    va_end(ap);
   /*4. 输出数据到串口1*/
   USARTx_StringSend(USART1,USART1_PRINTF_BUFF);
   //USART1_Printf("%d%s",123,454656); 
   //int data=va_arg(ap,int);
}

4.4 定时器部分代码

/*
函数功能: 配置定时器3
函数参数: psc 预分频器  arr重装载值
*/
void TIMER3_Init(u16 psc,u16 arr)
{
   /*1. 开时钟*/
   RCC->APB1ENR|=1<<1; //开启定时器3的时钟
   RCC->APB1RSTR|=1<<1;//开启定时器3复位时钟
   RCC->APB1RSTR&=~(1<<1);//关闭定时器3复位时钟
   /*2. 配置核心寄存器*/
   TIM3->PSC=psc-1;
   TIM3->ARR=arr;
   TIM3->DIER|=1<<0; //开启更新中断
   STM32_SetPriority(TIM3_IRQn,1,1); //设置中断优先级
  // TIM3->CR1|=1<<0; //开启定时器3
}
/*
函数功能: 定时器3中断服务函数
*/
void TIM3_IRQHandler(void)
{
    if(TIM3->SR&1<<0)
    {
      TIM3->SR&=~(1<<0);
      USART3_RX_FLAG=1; //表示接收完毕
      TIM3->CR1&=~(1<<0); //关闭定时器3
    }
}

4.5 主函数调用部分(STA+TCP客户端)示例

int main()
{
   u8 key,cnt=0;
   LED_Init();
   BEEP_Init();
   KEY_Init();
   USART1_Init(115200);
   USART3_Init(115200);//串口-WIFI
   TIMER3_Init(72,20000); //超时时间20ms
   USART1_Printf("正在初始化WIFI请稍等.\n");
   if(ESP8266_Init())
   {
      USART1_Printf("ESP8266硬件检测错误.\n");  
   }
   else
   {
      USART1_Printf("WIFI:%d\n",ESP8266_STA_TCP_Client_Mode("ChinaNet-wbyw","12345678","192.168.101.6",8088,1));
   }
   while(1)
   {    
        if(USART3_RX_FLAG)
        {
          USART3_RX_BUFFER[USART3_RX_CNT]='\0';
          USART1_Printf("%s",USART3_RX_BUFFER);
          USART3_RX_CNT=0;
          USART3_RX_FLAG=0;
        }
        key=KEY_Scan(0);
        if(key==2)
        {
            USARTx_StringSend(USART3,"AT+GMR\r\n");  //查看版本信息
        }
        else if(key==3)
        {
            USARTx_StringSend(USART3,"12345ABCD");  
        }
        else if(key==4) //退出透传模式
        {
            USARTx_StringSend(USART3,"+++");
        }
        else if(key==5) //发送AT
        {
            USARTx_StringSend(USART3,"AT+CIPSTATUS\r\n");  //查看状态信息
        }
   }
}
目录
相关文章
|
7天前
|
消息中间件 安全 Unix
SSH配置多台服务器之间的免密登陆以及登陆别名
SSH配置多台服务器之间的免密登陆以及登陆别名
18 1
|
13天前
|
网络协议 Python
pythonTCP客户端编程连接服务器
【4月更文挑战第6天】本教程介绍了TCP客户端如何连接服务器,包括指定服务器IP和端口、发送连接请求、处理异常、进行数据传输及关闭连接。在Python中,使用`socket`模块创建Socket对象,然后通过`connect()`方法尝试连接服务器 `(server_ip, server_port)`。成功连接后,利用`send()`和`recv()`进行数据交互,记得在通信完成后调用`close()`关闭连接,确保资源释放和程序稳定性。
|
22天前
|
弹性计算
2024年阿里云服务器不同实例规格与配置实时优惠价格整理与分享
2024年阿里云服务器的优惠价格新鲜出炉,有特惠云服务器也有普通优惠价格,本文为大家整理汇总了2024年阿里云服务器的优惠价格,包含特惠云服务器和其他配置云服务器的优惠价格。以便大家了解自己想购买的云服务器选择不同实例规格和带宽情况下的价格,仅供参考。
2024年阿里云服务器不同实例规格与配置实时优惠价格整理与分享
|
4天前
|
存储 弹性计算 安全
阿里云服务器2核2G、2核4G配置最新租用收费标准及活动价格参考
2核2G、2核4G配置是很多个人和企业建站以及部署中小型的web应用等场景时首选的云服务器配置,这些配置的租用价格也是用户非常关心的问题,本文为大家整理汇总了2024年阿里云服务器2核2G、2核4G配置不同实例规格及地域之间的收费标准,同时整理了这些配置最新活动价格,以供大家参考和选择。
阿里云服务器2核2G、2核4G配置最新租用收费标准及活动价格参考
|
7天前
|
域名解析 网络协议 应用服务中间件
阿里云服务器配置免费https服务
阿里云服务器配置免费https服务
|
10天前
|
数据采集
robots.txt配置 减小服务器压力
robots.txt配置 减小服务器压力
13 0
|
21天前
|
网络协议 Linux 网络安全
Linux服务器DNS服务器配置实现bind的正向解释和反向解释
Linux服务器DNS服务器配置实现bind的正向解释和反向解释
17 0
|
22天前
|
弹性计算 网络安全 虚拟化
ECS数据问题之升级配置预防数据丢失如何解决
ECS(Elastic Compute Service,弹性计算服务)是云计算服务提供商提供的一种基础云服务,允许用户在云端获取和配置虚拟服务器。以下是ECS服务使用中的一些常见问题及其解答的合集:
|
23天前
|
弹性计算 Kubernetes 安全
ECS选型推荐配置
在构建Kubernetes集群时,应避免使用过多小规格ECS,因它们可能带来网络限制、容量不足和资源碎片化问题。采用大规格ECS能提升网络性能,优化镜像拉取效率。选择Master节点时,要考虑集群规模,生产环境建议选择较高规格。Worker节点推荐使用CPU≥4核、内存≥8GiB的ECS,根据集群总核数和容错率来决定节点数量。当规模达1000核,可选用裸金属神龙服务器,它提供超强网络、零计算抖动和安全性能,适合大促等需快速扩展的场景。
25 1
|
27天前
|
弹性计算 固态存储 调度
2024年阿里云服务器配置选择指南,新手整理
阿里云服务器配置选择指南:个人用户推荐轻量应用服务器或ECS通用算力型u1,适合小型网站和轻量应用。企业用户应选择企业级独享型如ECS计算型c7、通用型g7,保证高性能计算需求。配置选择要考虑CPU内存比例、公网带宽和系统盘。轻量服务器提供2核2G3M和2核4G4M选项,ECS实例则有多种规格以适应不同业务场景。公网带宽建议至少5M,系统盘可选高效云盘、SSD或ESSD。详细信息见[阿里云服务器产品页](https://www.aliyun.com/product/ecs)。
64 3