1)esp8266_drive.h
#ifndef _esp8266_drive_H
#define _esp8266_drive_H
#include "system.h"
#include
#include
#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
#include
#include
#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,失败返回false
bool 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 反之false
bool 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,反之false
bool 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,反之fasle
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:
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, 反之false
bool 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, 反之false
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
{
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;
}
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
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 );
}
}
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());
}
}
}
ESP8266-WIFI数据透传 免费下载链接:
http://download.csdn.net/detail/it_boy__/9842033