ESP8266 是一种带低功耗 WIFI 功能的物联网芯片,单片机或 PC 机可以通过 AT 指令 与 ESP8266 进行通信,对 ESP8266 进行一些设置,从而使其成为“无线路由器”。将 ESP8266 模块与开发板进行连接后,通过下面的过程可以实现手机端发送 Led On 或 Led Off 控制 LED 灯的亮灭(还可以通过手机发送指令控制开发板完成其他各种各样的功能):
1、电脑对 ESP8266 进行设置
由于 ESP8266 的通信接口的电平和电脑的通信接口的电平逻辑不同,因此使用 ESP8266 和电脑通信时,就需要使用 USB 转 TTL 模块将双方的电平转换成都能识别的电平,具体的操作就是将 ESP8266 模块的 VCC、GND、UTXD、URXD 和 CH_PD 与 USB 转 TTL 模块的 3.3V、GND、RXD、TXD 和 3.3V 连接,剩下的 RST、GPIO0 和 GPIO2 引脚无需连接,然后打开电脑的串口助手(Nebula 板资料里面带的烧录工具也可以)进行以下步骤:
● 设置串口波特率为 115200(ESP8266 模块的默认波特率),选择发送模式为文本模式,然后发送 AT+RST 指令,成功后会返回一堆乱码 +ready。
● 发送 AT+CWMODE=2,设置 ESP8266 为 AP 模式。
● 发送 AT+CWSAP="ESP8266","123456789",1,3,设置 WIFI 名称、WIFI 密码、通道号及加密方式。
● 设置好前面两个步骤后,需要重启模块使设置生效,即发送 AT+RST。
● 发送 AT+CIPMUX=1,设置 ESP8266 为多路连接模式。
● 发送 AT+CIPSERVER=1,8080,设置服务器开启,端口号为 8080。设置完后,ESP8266 模块就可以作为一个无线路由器了。
● 最后还需要发送一条指令 AT+CIFSR 指令,用来查询 ESP8266 的 IP 地址,默认为 192.168.4.1。
设置完后,可以使用手机连接 ESP8266 了,具体步骤如下:
● 打开手机无线局域网,连接自己设置的无线。
● 连接完毕后,发送一条测试指令,之后可以在串口助手上面接收到。
● 由于最终想要用单片机驱动 ESP8266,因此需要将 ESP8266 的串口通信波特率改为单片机能够实现的波特率,以 9600 为例,发送一条 AT+CIOBAUD=9600,发送完毕后串口助手会返回“OK”,然后再发送 AT+RST 重启模块,ESP8266 模块的串口通信波特率就被更改为 9600。。
2、利用单片机和 ESP8266 进行通信
在 ESP8266 模块与电脑进行通信时,通过电脑的串口调试助手按顺序向 ESP8266 模块发送了五条指令,其中前三条指令只需要设置一次就可以,重启也不会失效。而后两条指令是需要重启后重新设置的:
AT+CIPMUX=1
AT+CIPSERVER=1,8080
也就是说,每次开启 ESP8266 模块,都需要重新向模块发送一遍这两条指令。之前是使用电脑上的串口调试助手向 ESP8266 模块发送指令的,现在需要用单片机向 ESP8266 发送这两条指令。将 ESP8266 模块的 VCC、GND、UTXD、URXD 和 CH_PD 与单片机的的 3.3V、GND(需要与单片机共地)、RXD、TXD 和 3.3V 连接(如果单片机没有 3.3V 电源,就需要采用 5V 转 3.3V 电源模块进行电压转换),然后将单片机发送指令的程序下载到单片机中,即可实现单片机向 ESP8266 模块发送指令。
具体程序如下:
esp8266.h
#ifndef _ESP8266_H
#define _ESP8266_H
#include "reg52.h"
/****下面为Esp8266.c中的函数声明****/
void delay_ms(unsigned int i);
void Usart_Init(void);
void SendChar(unsigned char c);
void SendStr(unsigned char *str);
void Esp8266_Init();
#endif
esp8266.c
#include "Esp8266.h"
/**********延时函数,i=1时延时约1ms**********/
void delay_ms(unsigned int i)
{
unsigned int j,k;
for(j=i;j>0;j--)
for(k=118;k>0;k--);
}
/**********串口初始化函数**********/
void Usart_Init(void)
{
TMOD=0x20; //定时器1工作在模式2,自动重装载模式
SCON=0x50; //串行口工作在模式1
TH1=0xFA;
TL1=0xFA; //定时器初值设定,波特率4800,晶振11.0592Mhz
PCON=0x80; //波特率加倍,最终波特率为9600
ES=0; //关闭串口中断,为单片机向ESP8266发送AT指令做准备
EA=1; //开启总中断
TR1=1; //开启定时器1
REN=1; //允许接收
}
/**********发送字符函数**********/
void SendChar(unsigned char c)
{
SBUF=c; //将要发送的字符送入SBUF
while(!TI); //发送完毕后,TI=1,此时退出while循环
TI=0; //清空发送状态
RI=0; //清空接收状态
}
/**********发送字符串指令**********/
void SendStr(unsigned char *str)
{
while(*str!='0') //当要发送的字符串没有发送到最后一位'0'时,继续发送字符
{
SendChar(*str); //调用发送字符指令,一个字符一个字符发送
str++; //每发送一次,地址加一,发送后面的字符
}
}
/**********ESP8266初始化函数**********/
void Esp8266_Init()
{
SendStr("AT+CIPMUX=1rn"); //发送AT+CIPMUX=1指令
delay_ms(1000);
SendStr("AT+CIPSERVER=1,8080rn"); //发送AT+CIPSERVER=1,8080指令
delay_ms(1000);
ES=1; //开启串口中断,为后续用串口接收信息做准备
}
main.c
#include "reg52.h"
#include "Esp8266.h"
void main(void)
{
Usart_Init(); //串口初始化
delay_ms(1000); //延时1s,给Esp8266反应时间
Esp8266_Init(); //Esp8266初始化
delay_ms(1000); //延时1s,给Esp8266反应时间
while(1);
}
通过上面的程序,ESP8266 已经成功被设置成一个路由器。
3、手机发送字符控制 LED 灯亮灭
通过 2 步,ESP8266 已经可以接收手机发送来的指令了,利用下面的程序可以实现对手机发送来的指令进行解析从而控制开发板上的 LED 灯的亮灭(只需要改动 main.c 中的程序即可)。
main.c:
#include "reg52.h"
#include "Esp8266.h"
#include "string.h"
sbit Led = P1^0;
unsigned char sign; //串口接收:后手机发来的信息的标志位
unsigned char i; //接受字符存放数组的下标
unsigned char receive[50]; //接收字符存放数组,此数组存放手机发来的字符串信息,保证数组中元素个数大于等于指令字符数即可
/****定义灯的亮灭指令****/
unsigned char *Led_On = "Led On"; //灯亮指令
unsigned char *Led_Off = "Led Off"; //灯灭指令
void Control(void);
void main(void)
{
Usart_Init(); //串口初始化
delay_ms(1000); //延时1s,给Esp8266反应时间
Esp8266_Init(); //Esp8266初始化
delay_ms(1000); //延时1s,给Esp8266反应时间
while(1)
{
Control();
}
}
void Control(void)
{
//用memcmp函数来比较接收数组receive和字符串指针Led_On中的内容
if(memcmp(receive,Led_On,6) == 0)
{
Led = 0;
//用memset函数清空数组,防止后续因接收字符个数不定及判断标准不定带来的错误
memset(receive,0,50);
}
//用memcmp函数来比较接收数组receive和字符串指针Led_Off中的内容
if(memcmp(receive,Led_Off,7) == 0)
{
Led = 1;
//用memset函数清空数组,防止后续因接收字符个数不定及判断标准不定带来的错误
memset(receive,0,50);
}
}
/*串口中断函数,用来接收ESP8266接收到手机发送的信息+IPD,x,x:中,':'后的信息*/
void Usart() interrupt 4
{
RI = 0; //手动清除接收标志位
if(sign == 1)
{
//因为单片机每产生一次串口中断,只能接收一个字符,因此要想接收多个字符,单片机就要产生多次中断,因此利用数组来对接收到的字符进行保存
receive[i] = SBUF; //接收到':'后,每进入一次中断,就向receive数组中存储一个字符
i++;
}
if(SBUF == ':'||i>0) //如果接收到了:或者i>0(接收到了:后面的字符),标志位sign置1,此时证明,再次接收的数据即为手机发送的数据
{
sign=1;
}
if(SBUF == 'n') //接收到最后一位时
{
i = 0; //i清零,等待下一条信息的接收
sign = 0; //标志位清零,等待下一次接收
}
}