ESP8266-WIFI之例程篇

来源:互联网 发布:android mac 编辑:程序博客网 时间:2024/05/18 00:21

1、ESP8266_drive驱动类文件

1)esp8266_drive.h

#ifndef _esp8266_drive_H#define _esp8266_drive_H#include "system.h"#include <stdio.h>#include <stdbool.h>#if defined ( __CC_ARM   )#pragma anon_unions#endif//ESP8266模式选择typedef enum{    STA,    AP,    STA_AP  }ENUM_Net_ModeTypeDef;//网络传输层协议,枚举类型typedef enum{     enumTCP,     enumUDP,} ENUM_NetPro_TypeDef;//连接号,指定为该连接号可以防止其他计算机访问同一端口而发生错误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;#define ESP8266_RST_Pin          GPIO_Pin_6    //复位管脚#define ESP8266_RST_Pin_Port     GPIOE    //复位 #define ESP8266_RST_Pin_Periph_Clock  RCC_APB2Periph_GPIOE       //复位时钟#define ESP8266_CH_PD_Pin     GPIO_Pin_7   //使能管脚#define ESP8266_CH_PD_Pin_Port     GPIOG   //使能端口#define ESP8266_CH_PD_Pin_Periph_Clock  RCC_APB2Periph_GPIOG                     //使能时钟#define ESP8266_RST_Pin_SetH     GPIO_SetBits(ESP8266_RST_Pin_Port,ESP8266_RST_Pin)#define ESP8266_RST_Pin_SetL     GPIO_ResetBits(ESP8266_RST_Pin_Port,ESP8266_RST_Pin)#define ESP8266_CH_PD_Pin_SetH     GPIO_SetBits(ESP8266_CH_PD_Pin_Port,ESP8266_CH_PD_Pin)#define ESP8266_CH_PD_Pin_SetL     GPIO_ResetBits(ESP8266_CH_PD_Pin_Port,ESP8266_CH_PD_Pin)#define ESP8266_USART(fmt, ...)  USART_printf (USART2, fmt, ##__VA_ARGS__)    //USART_printf是串口发送函数,在esp8266_public.c里面#define PC_USART(fmt, ...)   printf (fmt, ##__VA_ARGS__)       //这是串口打印函数,串口1,执行printf后会自动执行fput函数,重定向了printf。#define RX_BUF_MAX_LEN 1024       //最大字节数extern struct STRUCT_USART_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;    }; }ESP8266_Fram_Record_Struct;//功能函数void ESP8266_Init(u32 bound);void ESP8266_AT_Test(void);bool ESP8266_Send_AT_Cmd(char *cmd,char *ack1,char *ack2,u32 time);void ESP8266_Rst(void);bool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode);bool ESP8266_JoinAP( char * pSSID, char * pPassWord );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_SendString(FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId );bool ESP8266_UnvarnishSend ( void );void ESP8266_ExitUnvarnishSend ( void );u8 ESP8266_Get_LinkStatus ( void );#endif

2)esp8266_drive.c

#include "esp8266_drive.h"#include "SysTick.h"#include <stdio.h>  #include <string.h>  #include <stdbool.h>#include "sta_tcpclent_test.h"#include "esp8266_public.h"struct STRUCT_USART_Fram ESP8266_Fram_Record_Struct = { 0 };  //定义了一个数据帧结构体void USART3_Init(u32 bound){    GPIO_InitTypeDef GPIO_InitStructure;    USART_InitTypeDef USART_InitStructure;    NVIC_InitTypeDef NVIC_InitStructure;    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö    GPIO_Init(GPIOB, &GPIO_InitStructure);    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO    //Usart3 NVIC 配置    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;      //响应优先级0    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //USART_IRQn通道使能    NVIC_Init(&NVIC_InitStructure); //初始化NVIC    //USART3 配置    USART_InitStructure.USART_BaudRate = bound;//波特率    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据长度    USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位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(USART3, &USART_InitStructure); //初始化串口    USART_ITConfig(USART3, USART_IT_RXNE|USART_IT_IDLE, ENABLE);//配置了接收中断和总线空闲中断    USART_Cmd(USART3, ENABLE);      //串口外设使能    }void USART3_IRQHandler( void ){       u8 ucCh;    if(USART_GetITStatus( USART3, USART_IT_RXNE ) != RESET )    {        ucCh  = USART_ReceiveData( USART3 );        if(ESP8266_Fram_Record_Struct .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )         {            //留最后一位做结束位            ESP8266_Fram_Record_Struct .Data_RX_BUF[ ESP8266_Fram_Record_Struct .InfBit .FramLength ++ ]  = ucCh;           }                          }    if( USART_GetITStatus( USART3, USART_IT_IDLE ) == SET )                              //如果总线空闲    {        ESP8266_Fram_Record_Struct .InfBit .FramFinishFlag = 1;        ucCh = USART_ReceiveData( USART3 );                                                              //由软件序列清除中断标志位(先读USART_SR,然后读USART_DR)        TcpClosedFlag = strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;    }   }void USART2_Init(u32 bound){    GPIO_InitTypeDef GPIO_InitStructure;    USART_InitTypeDef USART_InitStructure;    NVIC_InitTypeDef NVIC_InitStructure;    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2  TXD    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     GPIO_Init(GPIOA, &GPIO_InitStructure);    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3  RXD    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;    GPIO_Init(GPIOA, &GPIO_InitStructure);    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             NVIC_Init(&NVIC_InitStructure);     //USART2    USART_InitStructure.USART_BaudRate = bound;    USART_InitStructure.USART_WordLength = USART_WordLength_8b;    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);     USART_ITConfig(USART2, USART_IT_RXNE|USART_IT_IDLE, ENABLE);    USART_Cmd(USART2, ENABLE);                    }void USART2_IRQHandler( void ){       u8 ucCh;    if(USART_GetITStatus( USART2, USART_IT_RXNE ) != RESET )    {        ucCh  = USART_ReceiveData( USART2 );        if(ESP8266_Fram_Record_Struct .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )         {            ESP8266_Fram_Record_Struct .Data_RX_BUF[ ESP8266_Fram_Record_Struct .InfBit .FramLength ++ ]  = ucCh;           }                          }    if( USART_GetITStatus( USART2, USART_IT_IDLE ) == SET )                                         //如果总线空闲    {        ESP8266_Fram_Record_Struct .InfBit .FramFinishFlag = 1;        ucCh = USART_ReceiveData( USART2 );                                                              //由软件序列清除中断标志位(先读USART_SR,然后读USART_DR)        TcpClosedFlag = strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;    }   }void ESP8266_Init(u32 bound){    GPIO_InitTypeDef GPIO_InitStructure;    RCC_APB2PeriphClockCmd(ESP8266_RST_Pin_Periph_Clock|ESP8266_CH_PD_Pin_Periph_Clock, ENABLE);    GPIO_InitStructure.GPIO_Pin = ESP8266_RST_Pin;                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     //复用推挽输出    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    //晶振频率    GPIO_Init(ESP8266_RST_Pin_Port, &GPIO_InitStructure);    GPIO_InitStructure.GPIO_Pin = ESP8266_CH_PD_Pin;                   GPIO_Init(ESP8266_CH_PD_Pin_Port, &GPIO_InitStructure);    USART2_Init(bound);    ESP8266_RST_Pin_SetH;    ESP8266_CH_PD_Pin_SetL; }//对ESP8266模块发送AT指令// cmd 待发送的指令// ack1,ack2;期待的响应,为NULL表不需响应,两者为或逻辑关系// time 等待响应时间//返回1发送成功, 0失败bool ESP8266_Send_AT_Cmd(char *cmd,char *ack1,char *ack2,u32 time){    ESP8266_Fram_Record_Struct .InfBit .FramLength = 0; //重新接收新的数据包    ESP8266_USART("%s\r\n", cmd);    if(ack1==0&&ack2==0)     //不需要接收数据    {                      return true;    }    delay_ms(time);   //延时    ESP8266_Fram_Record_Struct.Data_RX_BUF[ESP8266_Fram_Record_Struct.InfBit.FramLength ] = '\0';    //PC_USART("%s", ESP8266_Fram_Record_Struct .Data_RX_BUF);  printf("%s",ESP8266_Fram_Record_Struct .Data_RX_BUF);    if(ack1!=0&&ack2!=0)    {        return ( ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack1 ) ||                          ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack2 ) );    }    else if( ack1 != 0 )  //strstr(s1,s2);检测s2是否为s1的一部分,是返回该位置,否则返回false,它强制转换为bool类型了        return ( ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack1 ) );    else        return ( ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack2 ) );}//复位重启void ESP8266_Rst(void){    ESP8266_RST_Pin_SetL;    delay_ms(500);     ESP8266_RST_Pin_SetH;}//发送AT启动测试void ESP8266_AT_Test(void){    char count=0;    ESP8266_RST_Pin_SetH;    delay_ms(1000);     while(count < 10)    {        if(ESP8266_Send_AT_Cmd("AT","OK",NULL,500))         {            printf("OK\r\n");            return;        }        ESP8266_Rst();        ++ count;    }}//选择ESP8266的工作模式// enumMode 模式类型//成功返回true,失败返回falsebool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode){    switch ( enumMode )    {        case STA:            return ESP8266_Send_AT_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 );         case AP:            return ESP8266_Send_AT_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 );         case STA_AP:            return ESP8266_Send_AT_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 );         default:          return false;    }       }//ESP8266连接外部的WIFI//pSSID WiFi帐号//pPassWord WiFi密码//设置成功返回true 反之falsebool ESP8266_JoinAP( char * pSSID, char * pPassWord ){    char cCmd [120];    sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord );    return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 5000 );}//ESP8266 透传使能//enumEnUnvarnishTx  是否多连接,bool类型//设置成功返回true,反之falsebool ESP8266_Enable_MultipleId (FunctionalState enumEnUnvarnishTx ){    char cStr [20];    sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) );    return ESP8266_Send_AT_Cmd ( cStr, "OK", 0, 500 );}//ESP8266 连接服务器//enumE  网络类型//ip ,服务器IP//ComNum  服务器端口//id,连接号,确保通信不受外界干扰//设置成功返回true,反之faslebool 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:          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 )        sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr);    else        sprintf ( cCmd, "AT+CIPSTART=%s", cStr );    return ESP8266_Send_AT_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );}//透传使能//设置成功返回true, 反之falsebool ESP8266_UnvarnishSend ( void ){    if (!ESP8266_Send_AT_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ))        return false;    return         ESP8266_Send_AT_Cmd( "AT+CIPSEND", "OK", ">", 500 );}//ESP8266发送字符串//enumEnUnvarnishTx是否使能透传模式//pStr字符串//ulStrLength字符串长度//ucId 连接号//设置成功返回true, 反之falsebool 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    {        if ( ucId < 5 )            sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );        else            sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );        ESP8266_Send_AT_Cmd ( cStr, "> ", 0, 1000 );        bRet = ESP8266_Send_AT_Cmd ( pStr, "SEND OK", 0, 1000 );  }    return bRet;}//ESP8266退出透传模式void ESP8266_ExitUnvarnishSend ( void ){    delay_ms(1000);    ESP8266_USART( "+++" );    delay_ms( 500 );    }//ESP8266 检测连接状态//返回0:获取状态失败//返回2:获得ip//返回3:建立连接 //返回4:失去连接 u8 ESP8266_Get_LinkStatus ( void ){    if (ESP8266_Send_AT_Cmd( "AT+CIPSTATUS", "OK", 0, 500 ) )    {        if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "STATUS:2\r\n" ) )            return 2;        else if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "STATUS:3\r\n" ) )            return 3;        else if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "STATUS:4\r\n" ) )            return 4;           }    return 0;}

2、ESP8266的public文件

1)esp8266_public.h

#ifndef _esp8266_public_H#define _esp8266_public_H#include "system.h"void USART_printf( USART_TypeDef * USARTx, char * Data, ... );#endif

2)esp8266_public.c

#include "esp8266_public.h"#include <stdarg.h>static char *itoa( int value, char *string, int radix ){    int     i, d;    int     flag = 0;    char    *ptr = string;    /* This implementation only works for decimal numbers. */    if (radix != 10)    {        *ptr = 0;        return string;    }    if (!value)    {        *ptr++ = 0x30;        *ptr = 0;        return string;    }    /* if this is a negative value insert the minus sign. */    if (value < 0)    {        *ptr++ = '-';        /* Make the value positive. */        value *= -1;    }    for (i = 10000; i > 0; i /= 10)    {        d = value / i;        if (d || flag)        {            *ptr++ = (char)(d + 0x30);            value -= (d * i);            flag = 1;        }    }    /* Null terminate the string. */    *ptr = 0;    return string;} /* NCL_Itoa */void USART_printf ( USART_TypeDef * USARTx, char * Data, ... ){    const char *s;    int d;       char buf[16];    va_list ap;    va_start(ap, Data);    while ( * Data != 0 )     // 判断数据是否到达结束符    {                                                 if ( * Data == 0x5c )  //'\'        {                                                 switch ( *++Data )            {                case 'r':                                     //回车符                USART_SendData(USARTx, 0x0d);                Data ++;                break;                case 'n':                                     //换行符                USART_SendData(USARTx, 0x0a);                   Data ++;                break;                default:                Data ++;                break;            }                    }        else if ( * Data == '%')        {                                                 switch ( *++Data )            {                               case 's':                                         //字符串                s = va_arg(ap, const char *);                for ( ; *s; s++)                 {                    USART_SendData(USARTx,*s);                    while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );                }                Data++;                break;                case 'd':                               //十进制                d = va_arg(ap, int);                itoa(d, buf, 10);                for (s = buf; *s; s++)                 {                    USART_SendData(USARTx,*s);                    while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );                }                     Data++;                     break;                default:                     Data++;                     break;            }                }        else USART_SendData(USARTx, *Data++);        while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET );    }}

3、客户端(STA数据透传测试)

1)sta_tcpclent_test.h

#ifndef _sta_tcpclent_test_H#define _sta_tcpclent_test_H#include "system.h"#define User_ESP8266_SSID     "S237"          //wifi名#define User_ESP8266_PWD      "20152620"      //wifi密码#define User_ESP8266_TCPServer_IP     "192.168.1.106"     //服务器IP#define User_ESP8266_TCPServer_PORT   "8080"      //服务器端口号extern volatile uint8_t TcpClosedFlag;  //连接状态标志void ESP8266_STA_TCPClient_Test(void);#endif

2)sta_tcpclent_test.c

#include "sta_tcpclent_test.h"#include "SysTick.h"#include "usart.h"#include "esp8266_drive.h"volatile u8 TcpClosedFlag = 0;void ESP8266_STA_TCPClient_Test(void){    u8 res;    char str[100]={0};    printf ( "\r\正在配置esp8266,请耐心等待...\r\n" );    ESP8266_CH_PD_Pin_SetH;    ESP8266_AT_Test();    ESP8266_Net_Mode_Choose(STA);    while(!ESP8266_JoinAP(User_ESP8266_SSID, User_ESP8266_PWD));    ESP8266_Enable_MultipleId ( DISABLE );    while(!ESP8266_Link_Server(enumTCP, User_ESP8266_TCPServer_IP, User_ESP8266_TCPServer_PORT, Single_ID_0));    while(!ESP8266_UnvarnishSend());    printf ( "\r\nESP8266配置 OK\r\n" );    while ( 1 )    {               sprintf (str,"I am very good!\r\n" );  //格式化 即str = "I am very good!\r\n"        ESP8266_SendString ( ENABLE, str, 0, Single_ID_0 );        delay_ms(1000);        if(TcpClosedFlag) //判断是否失去连接        {            ESP8266_ExitUnvarnishSend(); //退出透传模式            do            {                res = ESP8266_Get_LinkStatus();     //获取连接状态            }               while(!res);            if(res == 4)                     //确认失去连接,重连            {                printf ( "\r\重新连接...\r\n" );                while (!ESP8266_JoinAP(User_ESP8266_SSID, User_ESP8266_PWD ) );                while (!ESP8266_Link_Server(enumTCP, User_ESP8266_TCPServer_IP, User_ESP8266_TCPServer_PORT, Single_ID_0 ) );                printf ( "\r\重新连接成功\r\n" );            }             while(!ESP8266_UnvarnishSend());                            }    }   }

4、其他工程文件请下载:

ESP8266-WIFI数据透传 免费下载链接:
http://download.csdn.net/detail/it_boy__/9842033

3 0
原创粉丝点击