工作模式:
- STA模式 别人创建WIFI网络,ESP8266加入该网络
- AP模式 产生WIFI网络
- STA+AP
物理层:
1.VCC 电源(3.3V~5V)
2 GND 电源地
3 TXD(TTL 电平,不能直接接 RS232 电平!),可接 单片机的 RXD
4 RXD(TTL 电平,不能直接接 RS232 电平!),可接 单片机的 TXD
5 RST 复位(低电平有效)
6 IO-0 进入固件烧写模式,低电平是烧写模式,高电平是运行模式(默认)
常用指令
命令 | 功能 | 备注 |
AT | 测试模块是否正常 | 基础指令 |
ATE1/ATE0 | 开启/关闭回显 | |
AT+CWMODE/AT+CWSAP_DEF | 设置AP模式及AP参数 | AT WIFI指令 |
AT +CWMODE=1 | 设置为Station 模式 | |
AT +CWJAP | 连接热点 | |
AT+CIPSTART | 建立TCP连接 | AT TCP指令 |
AT+CIPMODE=1 | 开启透传传输 | |
AT+CIPSEND | 发送数据 | |
+++ | 退出透传模式 | |
AT+CIPCLOSE | 关闭TCP连接 |
将电脑上面的串口助手上面AT指令发送给ESP8266:
电脑上面的串口助手 -- 串口1
- 首先USART1接收中断,接收上位机发过来的AT指令
- 将接收的AT指令,写入USART3->DR,就发送给ESP8266.
- ESP8266接收指令后,进行响应,响应的数据,使用USART3接收中断接收数据
为了看到esp8266响应的数据,将USART3接收的数据写入USART1->DR。
代码:
#include "esp32.h"
#include "delay.h"
#include "string.h"
#include "stdio.h"
NETDATA netdata={0};
/*************************************************
函数功能:WIFI模块
函数参数: 无
函数返回值: 无
**************************************************/
void esp32Init()
{
//ESP_RXD ---PA2 --复用推挽输出
//ESP_TXD ---PA3 --复用浮空输入
//1.使能时钟 --PA --USART2
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
//2.配置GPIOA 工作模式
//PA2复用推挽输出
GPIO_InitTypeDef WIFI_InitStruct={0};
WIFI_InitStruct.GPIO_Mode=GPIO_Mode_AF;
WIFI_InitStruct.GPIO_OType=GPIO_OType_PP; //配置为复用推挽输出
WIFI_InitStruct.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3;
WIFI_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL; //配置为空 输出(不需要配)
WIFI_InitStruct.GPIO_Speed=GPIO_High_Speed; //输出速度
GPIO_Init(GPIOA,&WIFI_InitStruct);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);
//3.配置串口
USART_InitTypeDef USART_InitStruct={0};
USART_InitStruct.USART_BaudRate=115200; //波特率
USART_InitStruct.USART_Mode =USART_Mode_Rx|USART_Mode_Tx; //接收模式与发送模式
USART_InitStruct.USART_Parity =USART_Parity_No; //禁止校验
USART_InitStruct.USART_StopBits = USART_StopBits_1; //停止位1位
USART_InitStruct.USART_WordLength=USART_WordLength_8b; //数据位8位
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //不使用硬件流控制
USART_Init(USART2,&USART_InitStruct);
//4.使能接收中断 串口 接收中断
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
//5.使能空闲中断
USART_ITConfig(USART2,USART_IT_IDLE,ENABLE);
//4-5配置NVIC
NVIC_InitTypeDef NVIC_InitStruct={0};
NVIC_InitStruct.NVIC_IRQChannel=USART2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStruct);
//6使能USART2
USART_Cmd(USART2,ENABLE);
}
//编写中断服务函数(在启动文件中)
void USART2_IRQHandler(void)
{
u8 data=0;
//先判断终端是否产生
//获取终端状态
if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET)//接收中断产生
{
USART_ClearITPendingBit(USART2,USART_IT_RXNE);//清中断
data = USART_ReceiveData(USART2);//保存串口助手发过来的AT指令集
netdata.rxbuff[netdata.rxcount++] = USART_ReceiveData(USART2);//保存串口助手发过来的AT指令集
USART_SendData(USART1,data);//转发AT指令到USART1以及串口上面
}
//获取终端状态
if(USART_GetITStatus(USART2,USART_IT_IDLE)==SET)//空闲中断产生
{
USART2->DR;
/*
清中断
--对于空闲中断清理 特殊在于:
需要先读取 SR USART_GetITStatus(USART2,USART_IT_IDLE)这个语句相当于读取了 SR
在读DR 就可以了
*/
}
}
/*———————————————————————————————————————————————————————————————————————————
函数功能: 发送一个字节函数
函数参数: 要发送的数据
函数返回值: 无
—————————————————————————————————————————————————————————————————————————————*/
void Usart2SendByte(uint8_t data)
{
//判断发送寄存器是否有数据-- 判断上次数据是否发送完成
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET);
USART_SendData(USART2,data);
}
/*———————————————————————————————————————————————————————————————————————————
函数功能: 发送字符串函数
函数参数: 要发送的数据
函数返回值: 无
———————————————————————————————————————————————————————————————————————————*/
void Usart2SendStr(char *data)
{
while(*data!='\0')
{
Usart2SendByte(*data++);
}
}
/*———————————————————————————————————————————————————————————————————————————
函数功能: 发送一定长度的函数
函数参数: 要发送的数据
函数返回值: 无
———————————————————————————————————————————————————————————————————————————*/
void Usart2Sendbuff(char *buff,u16 len)
{
u32 i=0;
for(i=0;i<len;i++)
{
Usart2SendByte(buff[i]);
}
}
ESP8266连接WIFI
- 首先测试ESP工作是否正常;发送“AT”指令,正常返回OK;
- 然后设置ESP工作模式;发送“AT +CWMODE=1”,设置成功返回“OK”;
- 连接WIFI;发送“AT+CWJAP="WIFI名","WIFI密码";设置成功返回“WIFI GOT IP”;
- 此时ESP已经连接上局域网。
连接服务器
- 在已经连接上局域网的前提下,建立TCP连接;发送“AT+CIPSTART="TCP","地址",“端口号”;设置成功返回“OK”。
- 设置透传模式;发送“AT+CIPMODE=1”,设置成功返回“OK”
- 设置发送数据指令模式;发送“AT+CIPSEND”,设置成功返回“>”
代码编写
#include "ESP8266.h"
#include "delay.h"
#include "string.h"
#include "stdio.h"
/*
函数功能:WIFI模块
函数参数: 无
函数返回值: 无
*/
NETDATA netdata={0};
void ESP8266Init()
{
//ESP_EN ---PE6 --通用推挽输出
//ESP_RXD ---PB10 --复用推挽输出
//ESP_TXD ---PB11 --浮空输入
//1.使能时钟 --PB PE 端口 --USART3
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
//2.配置GPIOB E 工作模式
//PB10复用推挽输出
GPIO_InitTypeDef GPIO_InitStruct={0};
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
//PB11复用浮空输入
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_11;
GPIO_Init(GPIOB,&GPIO_InitStruct);
//PE6通用推挽输出
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
GPIO_Init(GPIOE,&GPIO_InitStruct);
GPIO_SetBits(GPIOE,GPIO_Pin_6);
//3.配置串口
USART_InitTypeDef USART_InitStruct={0};
USART_InitStruct.USART_BaudRate=115200; //波特率
USART_InitStruct.USART_Mode =USART_Mode_Rx|USART_Mode_Tx; //接收模式与发送模式
USART_InitStruct.USART_Parity =USART_Parity_No; //禁止校验
USART_InitStruct.USART_StopBits = USART_StopBits_1; //停止位1位
USART_InitStruct.USART_WordLength=USART_WordLength_8b; //数据位8位
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //不使用硬件流控制
USART_Init(USART3,&USART_InitStruct);
//4.使能接收中断 串口 接收中断
USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
//5.使能空闲中断
USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);
//4-5配置NVIC
NVIC_InitTypeDef NVIC_InitStruct={0};
NVIC_InitStruct.NVIC_IRQChannel=USART3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStruct);
//6使能USART3
USART_Cmd(USART3,ENABLE);
}
//编写中断服务函数(在启动文件中)
void USART3_IRQHandler(void)
{
u8 data=0;
//先判断终端是否产生
//获取终端状态
if(USART_GetITStatus(USART3,USART_IT_RXNE)==SET)//接收中断产生
{
USART_ClearITPendingBit(USART3,USART_IT_RXNE);//清中断
data = USART_ReceiveData(USART3);//保存串口助手发过来的AT指令集
netdata.rxbuff[netdata.rxcount++]=USART_ReceiveData(USART3);
USART_SendData(USART1,data);//转发AT指令到USART1以及串口上面
}
//获取终端状态
if(USART_GetITStatus(USART3,USART_IT_IDLE)==SET)//空闲中断产生
{
USART3->DR;
/*
清中断
--对于空闲中断清理 特殊在于:
需要先读取 SR USART_GetITStatus(USART2,USART_IT_IDLE)这个语句相当于读取了 SR
在读DR 就可以了
*/
}
}
//发送一个字节函数
void Usart3SendByte(uint8_t data)
{
//判断发送寄存器是否有数据-- 判断上次数据是否发送完成
while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET);
USART_SendData(USART3,data);
}
//发送字符串函数
void Usart3SendStr(char *data)
{
while(*data!='\0')
{
Usart3SendByte(*data++);
}
}
void Esp8266ConnectHost(void)
{
NetSendCmdCheckAck("AT\r\n","OK",100,2);
NetSendCmdCheckAck("AT+CWMODE=1\r\n","OK",100,2);//设置为STA模式
NetSendCmdCheckAck("AT+CWJAP=\"LYJ\",\"11111111\"\r\n","WIFI GOT IP",10000,2);//连接热点
Delay_nms(2000);
NetSendCmdCheckAck("AT+CIPSTART=\"TCP\",\"122.114.122.174\",43491\r\n","OK",1000,2);//连接服务器
NetSendCmdCheckAck("AT+CIPMODE=1\r\n","OK",100,2);//设置透传模式
NetSendCmdCheckAck("AT+CIPSEND\r\n",">",100,2);//发送数据指令
Usart3SendStr("12345");//发送的数据
Delay_nms(5000);
Usart3SendStr("+++");//退出透传
Delay_nms(1000);
NetSendCmdCheckAck("AT+CIPCLOSE\r\n","OK",100,2);//退出服务器连接
}
//比对,查找目标字符串
//src 被检查的字符串
//dest :要查找的目标
char *FindStr(char *src,char *dest,uint16_t overtime)
{
while(strstr(src,dest)==NULL &&(overtime--) )
{
Delay_nms(1);
}
return strstr(src,dest);
}
/*
发送AT指令并检查应答
cmd: AT指令
ack: AT指令的回应数据
overtime:超时时间
cnt:循环发送次数
*/
uint8_t NetSendCmdCheckAck(char *cmd,char *ack,uint16_t overtime,u8 cnt)
{
memset(netdata.rxbuff,0,sizeof(netdata.rxbuff));
netdata.rxcount =0;
netdata.rxover =0;
if(*cmd)
{
do{
Usart3SendStr(cmd);
if(FindStr((char *)netdata.rxbuff,ack,overtime)!=NULL)
{
return 0;
}
else
{
printf("比对失败,指令重发\r\n");
}
}while(cnt--);
}
}