写点什么

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

作者:DS小龙哥
  • 2022 年 8 月 10 日
    重庆
  • 本文字数:7636 字

    阅读完需:约 25 分钟

ESP8266 是一款串口 WIFI 模组,内置了完善的网络协议栈,并且有完善的 AT 指令集,单片机可以通过串口控制 ESP8266 完成网络编程,在物联网领域使用非常多。有了这款 WIFI,这也降低了的物联网、嵌入式工程师的网络编程难度。这篇文章就详细介绍 ESP8266 的使用方法,介绍 AP 模式、STA 模式的配置方法,完成 TCP 服务器、TCP 客户端的创建。

一、硬件环境介绍

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



2. STM32 : 采用 STM32F103C8T6


3. 编程软件 : 采用 Keil5


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





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

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




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

硬件连接: 下面会贴出核心代码,在当前开发板上,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");  //查看状态信息         }    } }
复制代码

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);          }    } }
复制代码


发布于: 刚刚阅读数: 3
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
STM32封装ESP8266一键配置函数:实现实现AP模式和STA模式切换、服务器与客户端创建_8月月更_DS小龙哥_InfoQ写作社区