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
- ESP8266-WIFI之例程篇
- ESP8266-WIFI之简介
- Arduino - ESP8266 Wifi 模块 之 设置
- Arduino - ESP8266 Wifi 模块 之 搭建
- ESP8266 wifi模块使用
- <WIFI>初识ESP8266小黄板
- ESP8266 WIFI 模块使用说明
- ESP8266的WIFI连接
- ESP8266 WiFi探针 MAC
- ESP8266串口WiFi模块
- ESP8266链接WiFi
- ESP8266 SDK开发篇(二)——连接wifi
- ESP8266 基础篇:WiFi scan 方法以及测试
- <WIFI>搭建ESP8266开发环境
- STM32 wifi(ESP8266)模块实验
- esp8266 wifi模块的使用
- WiFi模块 ESP8266的用法
- esp8266使用micropython链接WiFi
- C++ Primer 第5版--练习11.12
- 安卓mvp教程
- [leetcode]17. Letter Combinations of a Phone Number
- Vue初体验(五)过滤器的使用
- 指针逃逸对JVM性能的影响
- ESP8266-WIFI之例程篇
- android-apt plugin is incompatible with future version of Android Gradle plugin. use 'annotationPro
- Spark中sortByKey和sortBy对(key,value)数据分别 根据key和value排序
- PS小技巧
- CodeForces794cNaming Company
- android性能优化
- Linux基础学习笔记之管道中如何将标准错误输出传递给下调命令?
- FFmpeg总结(十三)用ffmpeg基于nginx实现直播功能,不用第三方SDK,自研推流拉流
- Linux命令基础10-less命令