当前位置:网站首页>STM32封装ESP8266一键配置函数:实现实现AP模式和STA模式切换、服务器与客户端创建

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

2022-07-06 22:23:00 华为云

一、硬件环境介绍

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

2. STM32 : 采用STM32F103C8T6

3. 编程软件 : 采用Keil5
image.png
image.png

ESP8266编程调试过程中用到的相关软件下载地址:
image.png
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.255u8 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");  //查看状态信息        }   }}

4.6 主函数调用部分(AP+TCP服务器)示例

int main(){   u8 key;   LED_Init();   BEEP_Init();   KEY_Init();   USART1_Init(115200);   USART3_Init(115200);//串口-WIFI   TIMER3_Init(72,20000); //超时时间20ms    USART1_Printf("正在初始化WIFI请稍等.\n");   //初始化WIFI硬件   if(ESP8266_Init())USART1_Printf("WIFI硬件错误.\n");   else   {      //配置WIFI的模式      USART1_Printf("WIFI配置状态:%d\n",ESP8266_AP_TCP_Server_Mode("esp8266_666","12345678",8088));   }   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)        {           ESP8266_ServerSendData(0,(u8*)"1234567890",10);         }        else if(key==3)        {           ESP8266_ServerSendData(0,(u8*)"abcd",4);         }   }}
原网站

版权声明
本文为[华为云]所创,转载请带上原文链接,感谢
https://bbs.huaweicloud.com/blogs/363918