一、什么是Esp8266的AP模式

ESP8266支持3种模式:Station模式、AP模式和Station+AP混合模式。关于这三种模式的区别可以类比我们的手机,当手机连接无线网时,此时手机为Station模式,当手机打开移动热点时,此时手机为AP模式。简单的说就是Station模式就是作为终端,AP模式就是作为路由器。而Station+AP混合模式,就和路由器的无线桥接功能是一样的,既可以连接别的无线网,同时也可以自己作为路由器。
本文是使用AP模式进行与手机的连接,从而控制单片机。


二、ESP8266的准备工作

在使用ESP8266之前需要进行一些配置,因为esp8266是一款功能丰富的芯片,通常我更喜欢直接针对它进行开发,在我看来,单单作为无线传输模块来使用未免有些“大材小用”之感,作为Ap模式来工作与蓝牙模块也并无大的不同,如果读者对esp8266的其他的模式感兴趣,比如mqtt协议之类的,可以查看我之前的帖子,那应该是更成熟的物联网方案。
闲话少叙,首先我们要将esp8266与电脑连接然后随便下载一个串口调试助手,对芯片进行一些配置。esp8266与电脑之间的通过usb-ttl方式的连线网上有很多,这里就不多做赘述,我个人推荐淘宝买个esp8266的专用下载器,会省事很多,不要把时间浪费在与芯片下载斗智斗勇上,应该多关注开发。
我使用的串口调试软件是XCOMXCOM。下面贴调试命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
AT+CWMODE=2    //这个命令是为了配置esp8266工作模式为AP模式
返回值:OK

AT+CWSAP="ESP8266","123456789",11,0 //这条命令是用来配置芯片热点的名称和密码以及加密方式
返回值:OK

AT+RST // 重启模块

AT+UART=9600,8,1,0,0 //这条命令主要是设置波特率9600-波特率 8-8bit数据位 1-1bit停止位 0-none校验位 0-不使能流控。因为芯片波特率需要与单片机一致才能进行通信。
返回值:OK

AT+CIPMUX=1 //开启多连接,这句每次重启芯片都需要配置会写进代码里面
返回值:OK

AT+CIPSERVER=1,8080 //建立服务器,端口号8080,这句每次重启芯片都需要配置会写进代码里面
返回值:OK

通过串口助手依次输入以上命令之后,手机应该可以找到esp8266生成的一个wifi了,进行连接之后打开手机上的TCP网络调试助手,这个app网上有很多可以随便下一个,或者自己用androidstudio开发也并不会花很多时间,更重要的是自己开发你可以隐藏很多输入和命令,直接做成按钮事件,作为设计来说更为完善。
手机打开调试调试助手后,输入IP地址:192.168.4.1(通常默认为这个地址,可通过AT指令自查),端口号:8080(设置的数值)连接成功后随便发送一些消息给esp8266,比如hello,那么串口助手就会收到类似 +IPD,0,3:hello 这样的信息,这样我们芯片前期的配置工作就完成了。


三、单片机方面

首先将单片机与ESP8266连接起来,连接方式也很简单和USB-TTL连接基本一致:
| 51单片机 | 3.3V | GND | TXD | RXD | 3.3V |
|———|——|—–|—–|—–|———–|
| ESP8266 | VCC | GND | RXD | TXD | EN(ch_pd) |

因为51单片机引脚电压为5V,esp8266工作电压确实3.3v因此直接连接可能会导致芯片寿命缩短甚至损坏,因此建议接一个电平转换模块来进行电平转换,再不济也需接个分压电阻。
模块连接好之后就可以向单片机中烧写程序了,代码贴在下面,建议自己敲一遍而不是直接复制粘贴,可以加深你对代码的理解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include <reg52.h>
#include <stdio.h>
#include <string.h>
#define uchar unsigned char //对数据类型进行声明定义
#define uint unsigned int

sbit LED1 = P2^0;
sbit LED2 = P2^1;
sbit LED3 = P2^2;
sbit LED4 = P2^3; //用于调试的LED灯
sbit LED5 = P2^4;
sbit LED6 = P2^5;
sbit LED7 = P2^6;
sbit LED8 = P2^7; //手机可以控制的LED灯

uchar TX_Flag = 1; //发送状态标志位,1允许发送,0发送结束
uchar RX_Flag = 1; //接收状态标志位,1允许接收,0接收结束
uchar num=0; //接收超时判断
uchar Recivedata; //存储接收到的一个字节数据

uchar Recive_table[15];
uint i=0;

void ms_delay(uint n)
{
uint j,m;
for( m =n; m>0; m--)
for(j=110; j>0; j--);
}
void us_delay(uchar n)
{
while(n--);
}
/******************************************************************
函 数: void Usart_init()
功 能: 单片机初始化
参 数: 无
返回值: 无
*******************************************************************/
void Usart_init()
{
SCON = 0x50; //设置串行口工作在方式一,且启动串行口接收(REN=1)


TMOD = 0x20; //定时器1工作在方式2八位自动重装模式
TH1 = 0xfd;
TL1 = 0xfd;
TR1 = 1; //开启定时器1

PCON = 0x00; //波特率不加倍
SM0 = 0; //串口工作方式
SM1 = 1;
REN = 1; //串口接收允许
EA = 1; //打开全局中断
ES = 1; //允许串口中断
}
/******************************************************************
函 数: void Sent_AT(uchar *At_Comd)
功 能: AT指令发送
参 数: 字符串指针
返回值: 无
*******************************************************************/
void Sent_AT(uchar *At_Comd) //定义字符串指针指向AT指令
{
ES = 0;
while(*At_Comd != '\0') //字符串结束标志
{
SBUF = *At_Comd; //写入1个字节数据
while(!TI); //等待该字节数据发送完成
TI = 0; //发送标志位清零
us_delay(5);
At_Comd++; //指向下一个字节
}
}
/******************************************************************
函 数: void WIFI_Init(void)
功 能: wifi初始化
参 数: 无
返回值: 无
*******************************************************************/
void WIFI_Init()
{

ES = 0; //关闭串口中断,防止收发过程被打扰
while(TX_Flag == 1){
Sent_AT("AT+CIPMUX=1\r\n"); //调用发送函数
LED1=0; //表示发送正常
while(RX_Flag == 1) //检测模块是否返回OK
{
if(RI)
{
RI = 0;
Recivedata = SBUF; //保存当前接收到的1个字
if(Recivedata == 'K') //回传“OK”中的K表示配置完成
{
TX_Flag = 0; //标志位清零,跳出收发循环
RX_Flag = 0;
}
}
num++; //累加
if(num == 1000) //未收到OK或接收超时
{
num = 0;
RX_Flag = 0; //跳出接收查询,再次发送
}
}
}
TX_Flag = 1; //跳出循环,表示配置成功
RX_Flag = 1;
num = 0; //标志位还原
LED2 = 0; //可通过LED灯表示配置完成

while(TX_Flag == 1){
Sent_AT("AT+CIPSERVER=1,8080\r\n");
LED3=0;
while(RX_Flag == 1)
{
if(RI)
{
RI = 0;
Recivedata = SBUF;
if(Recivedata == 'K')
{
TX_Flag= 0;
RX_Flag = 0;
}
}
num++;
if(num == 1000)
{
num = 0;
RX_Flag = 0;
}
}
}
TX_Flag= 1;
RX_Flag = 1;
num = 0;
LED4 = 0;
ES=1;
}
/**********************主函数************************/
void main()
{
Usart_init();
ms_delay(5000);
WIFI_Init();
while(1); ///循环等待中断
}

/******************************************************************
函 数: void Uart_Interrupt() interrupt 4
功 能: 串口中断函数,将收到的字符存到Recive_table[]数组中
参 数: 无
返回值: 无
*******************************************************************/
void Uart_Interrupt() interrupt 4 //中断服务程序接收并处理数据
{
if(RI==1)
{
RI=0; //接收标志位清零
Recive_table[i] = SBUF; //将数据存入数组
if(Recive_table[0]=='+') //初步检测有用信息
{i++;}
else
{i=0;}
if(i>=10) //一组数据接收完成
{
LED5 = 0; //LED显示接收完成
if((Recive_table[0]=='+')&&(Recive_table[1]=='I')&&(Recive_table[2]=='P')&&(Recive_table[3]=='D'))
{ //检测有效信息
if((Recive_table[9]=='0'))
{
LED8=0;
}else if((Recive_table[9]=='1'))
{
LED8=1;
}
LED7=0; //发送信息不符合
i = 0;
}
LED6=0; //未接收到正确格式数据
i = 0;
}
}
else TI = 0;
}

一个常识性的问题——烧写程序的时候TXD和RXD引脚需置空否则会烧写失败,程序烧进单片机之后,按一下板子的复位按钮,如果看到ESP模块上面蓝色小灯闪了,证明开发板跟ESP-01模块通信正常。然后用手机连上WIFI,打开TCP助手,建立一个新连接,IP地址192.168.4.1,端口8080,如果发送一个1,开发板上的小灯亮了,发送0,灯灭了(可能根据led共阴接法和共阳接法不同而有所改变),说明一切正常,如果不是这样的话,那就需要自己找找原因了,比如led口的接口定义与代码中是否一致。


结束

我用开发板进行的一个简单的程序验证和测试,只是一个模板代码,具体需要实现什么功能就请自己修改吧。