小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】

    • 前言
    • 预备知识
    • 1.优化8266使用,监测AT执行结果
      • 1.1优化8266使用,监测AT执行结果核心思路
      • 1.2**建立发送联网指令成功,连接服务器指令成功,打开透模式成功,打开实时发送成功标志,并用`while`循环等待**
      • 1.3**在串口中断函数中建立判断接收到的数据是否是指令执行成功的返回值算法,并把标志置一关闭等待。**
      • 1.4**初始化串口需待机1秒,让`ESP8266`发送乱码**
      • 1.5**建立联网成功和打开透传模式指示灯。**
      • 1.6完整程序代码
      • 1.7直观调试ESP8266接收指令返回字符串——白盒接线调试
    • 2.优化8266,捕获联网失败的状态
      • 2.1优化8266,捕获联网失败的状态核心思路
      • 2.2检测ESP8266没有联网标志FAIL
      • 2.3解决卡`WIFI GOT IP` bug
      • 2.4实现第一次联网没连上然后第二次联网连上
      • 2.5完整程序代码
      • 2.6调试方法
    • 3.ESP8266工作位AP路由模式并当成服务器
      • 3.1ESP8266工作位AP路由模式并当成服务器核心思路
      • 3.2将ESP8266 wifi 模块通过USB转TTL连接电脑,打开ESP8266串口调试助手(配置端口为COM8,波特率为9600“根据自己电脑来配”)
      • 3.3通过`ESP8266串口调试助手`发送`AT+RST`实现`重启模块`
      • 3.4通过`ESP8266串口调试助手`发送`AT+CWMODE=3`实现配置模块工作在`双模模式`。
      • 3.5用`电脑`连接`ESP8266`提供的`热点。`
      • 3.6通过`ESP8266串口调试助手`发送`AT+CIPMUX=1`实现模块`使能多连接`
      • 3.7通过`ESP8266串口调试助手`发送`AT+CIPSERVER=1`实现模块`建立TCPServer`
      • 3.8打开`PC网络调试助手`连接`ESP8266模块`
      • 3.9通过`ESP8266串口调试助手`发送`AT+CIPSEND=0,4`在`0通道`上发送`4个字节`
      • 3.10通过`ESP8266串口调试助手`发送A`T+CIPCLOSE=0`断开`PC网络调试助手`
      • 3.11通过`PC网络调试助手`发送数据给`ESP8266模块`
    • 4. 51单片机当路由器和服务器模式控制
      • 4.1 51单片机当路由器和服务器模式控制核心思路
      • 4.2定义打开路由模式,打开使能多连接,建立服务器,发送16个字节数据给终端(`一个汉字占2字节,所以16字节刚好是“网络配置完毕!\r\n”所需要的字节`)指令字符串,定义指令执行成功等待标志,终端连接服务器成功标志。
      • 4.3在主函数中建立从打开路由模式到成功连接终端的小算法。
      • 4.4在串口中断函数中建立打开路由模式到建立服务器指令并连接中端的返回值检测以及发送指令开关灯算法
      • 4.5完整程序代码
      • 4.6调试方法
    • 结束语

前言

  本篇博文介绍的是用51单片机的串口通信的应用(ESP8266 WIFI 模块),包含优化8266使用,监测AT执行结果,优化8266,捕获联网失败的状态,ESP8266工作位AP路由模式并当成服务器,51单片机当路由器和服务器模式控制。看到这篇博文的朋友,可以先赞再看吗?

预备知识

  一、基本电路标识识别和接线,例如VCC,GND。
  二、C变量
  三、基本输入输出
  四、流程控制
  五、函数

  六、指针
  七,字符串

  如果以上知识不清楚,请自行学习后再来浏览。如果我有没例出的,请在评论区写一下。谢谢啦!

1.优化8266使用,监测AT执行结果

1.1优化8266使用,监测AT执行结果核心思路

  • 建立发送联网指令成功,连接服务器指令成功,打开透模式成功,打开实时发送成功标志,并用while循环等待
  • 在串口中断函数中建立判断接收到的数据是否是指令执行成功的返回值算法,并把标志置一关闭等待。
  • 初始化串口需待机1秒,让ESP8266发送乱码
  • 建立联网成功和打开透传模式指示灯。

1.2建立发送联网指令成功,连接服务器指令成功,打开透模式成功,打开实时发送成功标志,并用while循环等待

  • 定义全局字符型变量联网等等标志和执行指令成功标志
char con_Net_Flag        = 0;                                                   //定义联网等待标志
char at_OK_Flag          = 0;                                                   //定义指令执行成功等待标志
  • 运用while循环等待联网,连接服务器,打开透传模式,打开实时发送成功。
//发送联网指令
sendString(cNetwork);
//等待联网成功
while(!con_Net_Flag);
while(!at_OK_Flag);
at_OK_Flag      =0;       //回归初识状态方便下次使用。

//发送连接服务器指令
sendString(cServer);
//等待连接服务器成功
while(!at_OK_Flag);
at_OK_Flag      =0;

//发送打开透传模式指令
sendString(oTransparent);
//等待打开透传模式
while(!at_OK_Flag);
at_OK_Flag      =0;

//发送打开实时发送指令
sendString(rTimeT);
//等待打开实时发送
while(!at_OK_Flag);

1.3在串口中断函数中建立判断接收到的数据是否是指令执行成功的返回值算法,并把标志置一关闭等待。

  • 算法思路

  当我们成功发送联网指令并让ESP8266模块联网,ESP8266会返回WIFI GOT IP 。那么就可以通过判断返回的指令中第一个字符第六个字符是否是‘W’‘G’。若果是就可以让等待标志置1,使单片机不再等待,并清空承接字符串的缓冲器buffer。但如果返回的字符串是WIFI GOT IP 第一个第六个字符并不是‘W’和‘G’,我们可以定义一个过渡变量tmp来判断,让tmp承接SBUF串回来的字符,并对其做判断,如果tmp等于第一个字符,就让历循字符数组的变量i强制等于1。(注:对于连接服务器,打开透传,打开实时发送,打开灯的一系列操作也用此算法思路实现

  • 算法代码
tmp = SBUF;
if(tmp=='W' || tmp=='O' || tmp=='L')
{
    i = 0;
}
buffer[i++] = tmp;

if(buffer[0]=='W' && buffer[5]=='G')
{
    con_Net_Flag = 1;
    memset(buffer,'\0',SIZE);
}
if(buffer[0]=='O' && buffer[1]=='K')
{
    at_OK_Flag   = 1;
    memset(buffer,'\0',SIZE);
}
//如果用L-1指令开灯,L-0指令关灯
if(buffer[0]=='L' && buffer[2]=='1')  
{
    LED1 = 0;
    memset(buffer,'\0',SIZE);
}
if(buffer[0]=='L' && buffer[2]=='0')
{
    LED1 = 1;
    memset(buffer,'\0',SIZE);
}
if(i == SIZE)
{
    i = 0;
}

1.4初始化串口需待机1秒,让ESP8266发送乱码

//初始化串口,配置波特率
UartInit();
//休眠1秒,让ESP8266发送乱码
Delay1000ms();

1.5建立联网成功和打开透传模式指示灯。

  • LED1为联网成功指示灯,LED2为联网和打开透传模式成功指示灯。
sbit LED1 = P3^7;  //使用位定义声明LED1
sbit LED2 = P3^6;  //使用位定义声明LED2
  • 利用等待联网成功标志和等待打开透传模式标志置1时作为判断是否开灯标志。
if(con_Net_Flag)
{
    LED1 = 0;      //联网成功LED1亮
}
if(at_OK_Flag)
{
    LED2 = 0;      //联网和打开透传模式成功LED2亮
}

1.6完整程序代码

#include "reg52.h"
#include "string.h"
#include "intrins.h"
#define SIZE 32

sfr AUXR = 0x8e;   //声明AUXR寄存器地址
sbit LED1 = P3^7;  //使用位定义声明LED1
sbit LED2 = P3^6;  //使用位定义声明LED2

char buffer[SIZE];                                                              //接收返回指令标志
code char cNetwork[]     = "AT+CWJAP=\"a\",\"123456789\"\r\n";                  //连接网络指令,\"为转译功能,code的功能是单独存放大数据
code char cServer[]      = "AT+CIPSTART=\"TCP\",\"192.168.253.12\",5000\r\n";   //连接服务器
char oTransparent[]      = "AT+CIPMODE=1\r\n";                                  //打开透传
char rTimeT[]            = "AT+CIPSEND\r\n";                                    //打开实时发送
char con_Net_Flag        = 0;                                                   //定义联网等待标志
char at_OK_Flag          = 0;                                                   //定义指令执行成功等待标志

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void UartInit(void)		//自己配
{
	//配置串口工作方式为方式1,从只收不发改为能收能发
	SCON =  0x50;
  //配置辅助寄存器,减少电磁辐射,稳定晶振频率  
	AUXR =  0x01;
	//设置定时器工作方式为定时器1的8位自动重装
	TMOD &= 0x0F;
	TMOD |= 0x20;
	//设置串口波特率为9600,0误差
	TH1   = 0xFD;
	TL1   = 0xFD;
	//打开定时器1
	TR1   = 1;
	//打开总中断
	EA = 1;
	//打开串口中断
	ES = 1;
}                                   

void sendByte(char data_mas)
{
	SBUF = data_mas;
	while(!TI);
	TI = 0;          //一定要软件置零,不然会出现乱序
}

void sendString(char *str)
{
	while(*str != '\0')
	{
		sendByte(*str);
		str++;
	}
}

void main()
{
	//初始化串口,配置波特率
	UartInit();
	//休眠1秒,让ESP8266发送乱码
	Delay1000ms();
	
	//初始化状态灯,使熄灭。
	LED1 = 1;
	LED2 = 1;
	
	//发送联网指令
	sendString(cNetwork);
	//等待联网成功
	while(!con_Net_Flag);
	while(!at_OK_Flag);
	at_OK_Flag      =0;       //回归初识状态方便下次使用。
	
	//发送连接服务器指令
	sendString(cServer);
	//等待连接服务器成功
	while(!at_OK_Flag);
	at_OK_Flag      =0;
	
	//发送打开透传模式指令
	sendString(oTransparent);
	//等待打开透传模式
	while(!at_OK_Flag);
	at_OK_Flag      =0;
	
	//发送打开实时发送指令
	sendString(rTimeT);
	//等待打开实时发送
	while(!at_OK_Flag);
	
	if(con_Net_Flag)
	{
		LED1 = 0;      //联网成功LED1亮
	}
	if(at_OK_Flag)
	{
    LED2 = 0;      //联网和打开透传模式成功LED2亮
	}
	//每延时1秒向电脑发送数据a
		/*Delay1000ms();		
		sendString("一起来学串口通信!!!\r\n");  //\r\n 为串口中的换行,缺一不可
		//怎么知道PC发了数据:由手册可知RI位为接受中断标志位,所以用查询的方法来判断RI是否等于1来开关灯*/
	while(1)
	{
		sendString("网络配置完毕!\r\n");
		Delay1000ms();
	}
} 

void UART_handler() interrupt 4
{
	//定义临时变量tmp用于判断接收的字符是否是需要的首字符。
	char tmp;
	//定义一个静态整型变量,在多次函数调用中只被执行一次初始化
	static int i = 0;
	//在串口中段函数中可以对发送接收中断标志进行处理
	if(RI == 1)
		{
			RI = 0;     //必须软件置零
			
			tmp = SBUF;
			if(tmp=='W' || tmp=='O' || tmp=='L')
			{
         		i = 0;
			}
			buffer[i++] = tmp;
			
			if(buffer[0]=='W' && buffer[5]=='G')
			{
				con_Net_Flag = 1;
				memset(buffer,'\0',SIZE);
			}
			if(buffer[0]=='O' && buffer[1]=='K')
			{
				at_OK_Flag   = 1;
				memset(buffer,'\0',SIZE);
			}
			//如果用1指令开灯,0指令关灯
			if(buffer[0]=='L' && buffer[2]=='1')  
			{
				LED1 = 0;
				memset(buffer,'\0',SIZE);
			}
			if(buffer[0]=='L' && buffer[2]=='0')
			{
				LED1 = 1;
				memset(buffer,'\0',SIZE);
			}
			
			if(i == SIZE)
			{
				i = 0;
			}
		}
		
	
	if(TI);
		
}

1.7直观调试ESP8266接收指令返回字符串——白盒接线调试

  • 白盒接线请看上篇

  • 调试思路

  分别打开单片机下载器的串口助手PC网络调试助手配置服务器ESP8266调试助手。启动单片机,当看到ESP8266调试助手显示WIFI GOT IP时通过单片机下载器的串口助手发送WIFI GOT IP,当看到ESP8266调试助手显示OK时通过单片机下载器的串口助手发送OK。直到看见PC网络调试助手接收区显示“网络配置成功!”字样即调试完毕。

  • 调试过程

  请私信我。

2.优化8266,捕获联网失败的状态

2.1优化8266,捕获联网失败的状态核心思路

  • 检测ESP8266没有联网标志FAIL
  • 解决卡WIFI GOT IP bug
  • 实现第一次联网没连上然后第二次联网连上并连接服务器

2.2检测ESP8266没有联网标志FAIL

  • 思路与1.3的算法思路一致
  • 检测ESP8266没有联网标志FAIL代码
if(tmp=='W' || tmp=='O' || tmp=='L' || tmp=='F')
{
    i = 0;
}


if(buffer[0]=='F' && buffer[1] == 'A')
{
    statusLED1();
    sendString(RESET);
    Delay1000ms();
    sendString(cNetwork);
    memset(buffer,'\0',SIZE);
}

2.3解决卡WIFI GOT IP bug

  • WIFI GOT IP bug的现象

  当在串口中断函数中加入检测ESP8266联网失败标志FAIL代码时,如果能够正常联网,则会卡主不执行。用白盒调试,会发现在连接好网络后,通过单片机下载器串口助手发送卡WIFI GOT IP 然后再发送OK都不会继续执行发送连接服务器指令和后续指令。while(!con_Net_Flag);是个延时bug。我在这里尝试了很多办法去解决,只有将while(!con_Net_Flag);

  • 如何解决卡WIFI GOT IP bug的现象

  bug出现的原因是:while(!con_Net_Flag);是个延时bug。

  我在这里尝试了很多办法去解决,只有将while(!con_Net_Flag);和中断函数中检测WIFI GOT IP的代码if(buffer[0]\=='W' && buffer[5]=='G'){con_Net_Flag = 1;memset(buffer,'\0',SIZE);}注释掉既可以解决。

2.4实现第一次联网没连上然后第二次联网连上

if(buffer[0]=='F' && buffer[1] == 'A')   进入联网失败检测代码
{
    statusLED1();                        操作LED1闪烁5sendString(RESET);                   发送重启ESP8266WiFi模块指令
    Delay1000ms();                       等待1sendString(cNetwork);                发送联网指令,这一步实现重新联网。
    memset(buffer,'\0',SIZE);            清除buffer里面的字符。
}

2.5完整程序代码

#include "reg52.h"
#include "string.h"
#include "intrins.h"
#define SIZE 32

sfr AUXR = 0x8e;   //声明AUXR寄存器地址
sbit LED1 = P3^7;  //使用位定义声明LED1
sbit LED2 = P3^6;  //使用位定义声明LED2

char buffer[SIZE];                                                              //接收返回指令标志
code char cNetwork[]     = "AT+CWJAP=\"a\",\"123456789\"\r\n";                  //连接网络指令,\"为转译功能,code的功能是单独存放大数据
code char cServer[]      = "AT+CIPSTART=\"TCP\",\"192.168.253.12\",5000\r\n";   //连接服务器
char oTransparent[]      = "AT+CIPMODE=1\r\n";                                  //打开透传
char rTimeT[]            = "AT+CIPSEND\r\n";                                    //打开实时发送
char RESET[]             = "AT+RST\r\n";                                        //重启指令
//char con_Net_Flag        = 0;                                                   //定义联网等待标志,这个标志会卡,不要用
char at_OK_Flag          = 0;                                                   //定义指令执行成功等待标志

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void UartInit(void)		//自己配
{
	//配置串口工作方式为方式1,从只收不发改为能收能发
	SCON =  0x50;
  //配置辅助寄存器,减少电磁辐射,稳定晶振频率  
	AUXR =  0x01;
	//设置定时器工作方式为定时器1的8位自动重装
	TMOD &= 0x0F;
	TMOD |= 0x20;
	//设置串口波特率为9600,0误差
	TH1   = 0xFD;
	TL1   = 0xFD;
	//打开定时器1
	TR1   = 1;
	//打开总中断
	EA = 1;
	//打开串口中断
	ES = 1;
}                                   

void sendByte(char data_mas)
{
	SBUF = data_mas;
	while(!TI);
	TI = 0;          //一定要软件置零,不然会出现乱序
}

void sendString(char *str)
{
	while(*str != '\0')
	{
		sendByte(*str);
		str++;
	}
}

void statusLED1()
{
	char i;
	
	for(i=0; i<5; i++)
	{
		LED1 = 0;
		Delay500ms();
		LED1 = 1;
		Delay500ms();
	}
}

int main()
{
	//初始化串口,配置波特率
	UartInit();
	//休眠1秒,让ESP8266发送乱码
	Delay1000ms();
	
	//初始化状态灯,使熄灭。
	LED1 = 1;
	LED2 = 1;
	
	//发送联网指令
	sendString(cNetwork);
	//等待联网成功
	//while(!con_Net_Flag);
	while(!at_OK_Flag);
	at_OK_Flag      =0;       //回归初识状态方便下次使用。
	
	//发送连接服务器指令
	sendString(cServer);
	//等待连接服务器成功
	while(!at_OK_Flag);
	at_OK_Flag      =0;
	
	//发送打开透传模式指令
	sendString(oTransparent);
	//等待打开透传模式
	while(!at_OK_Flag);
	at_OK_Flag      =0;
	
	//发送打开实时发送指令
	sendString(rTimeT);
	//等待打开实时发送
	while(!at_OK_Flag);
	if(at_OK_Flag)
	{
    LED1 = 0;
		LED2 = 0;      //联网和打开透传模式成功LED2亮
	}
	//每延时1秒向电脑发送数据a
		/*Delay1000ms();		
		sendString("一起来学串口通信!!!\r\n");  //\r\n 为串口中的换行,缺一不可
		//怎么知道PC发了数据:由手册可知RI位为接受中断标志位,所以用查询的方法来判断RI是否等于1来开关灯*/
	while(1)
	{
		sendString("网络配置完毕!\r\n");
		Delay1000ms();
	}
} 

void UART_handler() interrupt 4
{
	//定义临时变量tmp用于判断接收的字符是否是需要的首字符。
	char tmp;
	//定义一个静态整型变量,在多次函数调用中只被执行一次初始化
	static int i = 0;
	//在串口中段函数中可以对发送接收中断标志进行处理
	if(RI == 1)
		{
			RI = 0;     //必须软件置零
			
			tmp = SBUF;
			if(tmp=='W' || tmp=='O' || tmp=='L' || tmp=='F')
			{
				i = 0;
			}
			buffer[i++] = tmp;
			
			/*if(buffer[0]=='W' &&  buffer[5]=='G')
			{
				con_Net_Flag = 1;
				memset(buffer,'\0',SIZE);
			}*/
			if(buffer[0]=='O' && buffer[1]=='K')
			{
				at_OK_Flag   = 1;
				memset(buffer,'\0',SIZE);
			}
			if(buffer[0]=='F' && buffer[1] == 'A')
			{
				statusLED1();
				sendString(RESET);
				Delay1000ms();
				sendString(cNetwork);
				memset(buffer,'\0',SIZE);
			}
			//如果用1指令开灯,0指令关灯
			if(buffer[0]=='L' && buffer[2]=='1')  
			{
				LED1 = 0;
				memset(buffer,'\0',SIZE);
			}
			if(buffer[0]=='L' && buffer[2]=='0')
			{
				LED1 = 1;
				memset(buffer,'\0',SIZE);
			}
			
			if(i == SIZE)
			{
				i = 0;
			}
		}
		
	
	if(TI);
		
}

2.6调试方法

  调试方法用白盒调试法。

3.ESP8266工作位AP路由模式并当成服务器

3.1ESP8266工作位AP路由模式并当成服务器核心思路

  • ESP8266 wifi 模块通过USB转TTL连接电脑,打开ESP8266串口调试助手(配置端口为COM8,波特率为9600“根据自己电脑来配”)
  • 通过ESP8266串口调试助手发送AT+RST实现重启模块
  • 通过ESP8266串口调试助手发送AT+CWMODE=3实现配置模块工作在双模模式
  • 电脑连接ESP8266提供的热点。
  • 通过ESP8266串口调试助手发送AT+CIPMUX=1实现模块使能多连接
  • 通过ESP8266串口调试助手发送AT+CIPSERVER=1实现模块建立TCPServer
  • 打开PC网络调试助手连接ESP8266模块
  • 通过ESP8266串口调试助手发送AT+CIPSEND=0,40通道上发送4个字节
  • 通过ESP8266串口调试助手发送AT+CIPCLOSE=0断开PC网络调试助手

3.2将ESP8266 wifi 模块通过USB转TTL连接电脑,打开ESP8266串口调试助手(配置端口为COM8,波特率为9600“根据自己电脑来配”)

  • 接线方式

  TXD——RXD

  RXD——TXD

  5V ——3V3

  GND——GND

  • 打开ESP8266串口调试助手(配置端口为COM8,波特率为9600“根据自己电脑来配”)

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第1张图片

3.3通过ESP8266串口调试助手发送AT+RST实现重启模块

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第2张图片

3.4通过ESP8266串口调试助手发送AT+CWMODE=3实现配置模块工作在双模模式

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第3张图片

3.5用电脑连接ESP8266提供的热点。

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第4张图片

3.6通过ESP8266串口调试助手发送AT+CIPMUX=1实现模块使能多连接

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第5张图片

3.7通过ESP8266串口调试助手发送AT+CIPSERVER=1实现模块建立TCPServer

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第6张图片

3.8打开PC网络调试助手连接ESP8266模块

  • 通过ESP8266串口调试助手发送AT+CIFSR实现查询ESP8266模块IP地址

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第7张图片

  • PC命令提示符中输入ipconfig查询电脑IP地址

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第8张图片小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第9张图片

  • 打开PC网络调试助手进行连接

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第10张图片
小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第11张图片

3.9通过ESP8266串口调试助手发送AT+CIPSEND=0,40通道上发送4个字节

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第12张图片
小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第13张图片

3.10通过ESP8266串口调试助手发送AT+CIPCLOSE=0断开PC网络调试助手

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第14张图片

3.11通过PC网络调试助手发送数据给ESP8266模块

小小ESP8266居然有这么大的作用!!!可以让手机电脑通过wifi控制LED。#ESP8266 wifi 模块【下】_第15张图片

4. 51单片机当路由器和服务器模式控制

4.1 51单片机当路由器和服务器模式控制核心思路

  • 定义打开路由模式,打开使能多连接,建立服务器,发送16个字节数据给终端(一个汉字占2字节,所以16字节刚好是“网络配置完毕!\r\n”所需要的字节)指令字符串,定义指令执行成功等待标志,终端连接服务器成功标志。
  • 在主函数中建立从打开路由模式到成功连接终端的小算法。
  • 在串口中断函数中建立打开路由模式到建立服务器指令并连接中端的返回值检测以及发送指令开关灯算法
  • 注:本程序基于优化8266,捕获联网失败的状态工程建立

4.2定义打开路由模式,打开使能多连接,建立服务器,发送16个字节数据给终端(一个汉字占2字节,所以16字节刚好是“网络配置完毕!\r\n”所需要的字节)指令字符串,定义指令执行成功等待标志,终端连接服务器成功标志。

char routeMode[]         = "AT+CWMODE=2\r\n";                                   //打开路由模式
char moreJoin[]          = "AT+CIPMUX=1\r\n";                                   //打开使能多连接
char setUpServer[]       = "AT+CIPSERVER=1\r\n";                                //建立服务器
char sendData[]          = "AT+CIPSEND=0,16\r\n";                               //发送16个字节数据给终端
char at_OK_Flag          = 0;                                                   //定义指令执行成功等待标志
char at_Cli_Con_Flag     = 0;                                                   //终端连接服务器标志

4.3在主函数中建立从打开路由模式到成功连接终端的小算法。

  • 算法思路在程序注释中
  • 算法代码
//发送打开路由模式
sendString(routeMode);
//等待指令执行成功返回OK
while(!at_OK_Flag);
//让OK标志的值返回零,方便下次使用
at_OK_Flag = 0;

//发送打开使能多链接
sendString(moreJoin);
//等待指令执行成功返回OK
while(!at_OK_Flag);
//让OK标志的值返回零,方便下次使用
at_OK_Flag = 0;

//发送建立服务器指令
sendString(setUpServer);
//等待指令执行成功返回OK
while(!at_OK_Flag);
if(at_OK_Flag)
{
    statusLED1(); //建立服务器完成后让LED1闪烁5次,方便用PC网络助手连接
}
//让OK标志的值返回零,方便下次使用
at_OK_Flag = 0;
//等待PC网络助手连接
while(!at_Cli_Con_Flag);

//PC网络助手连接成功让两颗LED亮
if(at_Cli_Con_Flag) 
{
    LED1 = 0;
    LED2 = 0;
}

4.4在串口中断函数中建立打开路由模式到建立服务器指令并连接中端的返回值检测以及发送指令开关灯算法

  • 算法思路在程序注释中

  • 算法代码

//检测通过串口传回的数据是否是0开头,O开头,:开头,如果是,强行将字符数组标号置0
if(tmp=='0' || tmp=='O' || tmp==':')
{
    i = 0;
}
//将tmp中的字符串存入buffer中
buffer[i++] = tmp;

//检测返回的字符串是否为OK,是就将OK标志置1,退出等待循环
if(buffer[0]=='O' && buffer[1]=='K')
{
    at_OK_Flag        = 1;
    memset(buffer,'\0',SIZE);
}

//检测返回的字符串是否为0,C开始,是就将连接终端标志置1,退出等待循环
if(buffer[0]=='0' && buffer[2]=='C')
{
    at_Cli_Con_Flag   = 1;
    memset(buffer,'\0',SIZE);
}

//如果用op指令开灯,cl指令关灯
//检测返回的字符是否为:op和:cl开始,:op时打开灯,:cl时关灯
if(buffer[0]==':' && buffer[1]=='o' && buffer[2]=='p')  
{
    LED1 = 0;
    memset(buffer,'\0',SIZE);
}
if(buffer[0]==':' && buffer[1]=='c' && buffer[2]=='l')
{
    LED1 = 1;
    memset(buffer,'\0',SIZE);
}
//防止指针越界
if(i == SIZE)
{
    i = 0;
}

4.5完整程序代码

#include "reg52.h"
#include "string.h"
#include "intrins.h"
#define SIZE 32

sfr AUXR = 0x8e;   //声明AUXR寄存器地址
sbit LED1 = P3^7;  //使用位定义声明LED1
sbit LED2 = P3^6;  //使用位定义声明LED2

char buffer[SIZE];                                                              //接收返回指令标志
char routeMode[]         = "AT+CWMODE=2\r\n";                                   //打开路由模式
char moreJoin[]          = "AT+CIPMUX=1\r\n";                                   //打开使能多连接
char setUpServer[]       = "AT+CIPSERVER=1\r\n";                                //建立服务器
char sendData[]          = "AT+CIPSEND=0,16\r\n";                               //发送16个字节数据给终端
char at_OK_Flag          = 0;                                                   //定义指令执行成功等待标志
char at_Cli_Con_Flag     = 0;                                                   //终端连接服务器标志

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void UartInit(void)		//自己配
{
	//配置串口工作方式为方式1,从只收不发改为能收能发
	SCON =  0x50;
  //配置辅助寄存器,减少电磁辐射,稳定晶振频率  
	AUXR =  0x01;
	//设置定时器工作方式为定时器1的8位自动重装
	TMOD &= 0x0F;
	TMOD |= 0x20;
	//设置串口波特率为9600,0误差
	TH1   = 0xFD;
	TL1   = 0xFD;
	//打开定时器1
	TR1   = 1;
	//打开总中断
	EA = 1;
	//打开串口中断
	ES = 1;
}                                   

void sendByte(char data_mas)
{
	SBUF = data_mas;
	while(!TI);
	TI = 0;          //一定要软件置零,不然会出现乱序
}

void sendString(char *str)
{
	while(*str != '\0')
	{
		sendByte(*str);
		str++;
	}
}

void statusLED1()
{
	char i;
	
	for(i=0; i<5; i++)
	{
		LED1 = 0;
		Delay500ms();
		LED1 = 1;
		Delay500ms();
	}
}

int main()
{
	//初始化串口,配置波特率
	UartInit();
	//休眠1秒,让ESP8266发送乱码
	Delay1000ms();
	
	//初始化状态灯,使熄灭。
	LED1 = 1;
	LED2 = 1;
	
	//发送打开路由模式
	sendString(routeMode);
	//等待指令执行成功返回OK
	while(!at_OK_Flag);
	//让OK标志的值返回零,方便下次使用
	at_OK_Flag = 0;
	
	//发送打开使能多链接
	sendString(moreJoin);
	//等待指令执行成功返回OK
	while(!at_OK_Flag);
	//让OK标志的值返回零,方便下次使用
	at_OK_Flag = 0;
	
	//发送建立服务器指令
	sendString(setUpServer);
	while(!at_OK_Flag);
	if(at_OK_Flag)
	{
		statusLED1(); //建立服务器完成后让LED1闪烁5次,方便用PC网络助手连接
	}
	//让OK标志的值返回零,方便下次使用
	at_OK_Flag = 0;
	//等待PC网络助手连接
	while(!at_Cli_Con_Flag);
	
	//PC网络助手连接成功让两颗LED亮
	if(at_Cli_Con_Flag) 
	{
		LED1 = 0;
		LED2 = 0;
	}
	
	while(1)
	{
		//发送12个字节数据给终端指令
		sendString(sendData);
		//延时2秒
		Delay1000ms();
		Delay1000ms();
		//发送网络配置完毕数据
		sendString("网络配置完毕!\r\n");
		Delay1000ms();
		Delay1000ms();
	}
} 

void UART_handler() interrupt 4
{
	//定义临时变量tmp用于判断接收的字符是否是需要的首字符。
	char tmp;
	//定义一个静态整型变量,在多次函数调用中只被执行一次初始化
	static int i = 0;
	//在串口中段函数中可以对发送接收中断标志进行处理
	if(RI == 1)
    {
        RI = 0;     //必须软件置零

        tmp = SBUF;
        //检测通过串口传回的数据是否是0开头,O开头,:开头,如果是,强行将字符数组标号置0
        if(tmp=='0' || tmp=='O' || tmp==':')
        {
            i = 0;
        }
        //将tmp中的字符串存入buffer中
        buffer[i++] = tmp;

        //检测返回的字符串是否为OK,是就将OK标志置1,退出等待循环
        if(buffer[0]=='O' && buffer[1]=='K')
        {
            at_OK_Flag        = 1;
            memset(buffer,'\0',SIZE);
        }

        //检测返回的字符串是否为0,C开始,是就将连接终端标志置1,退出等待循环
        if(buffer[0]=='0' && buffer[2]=='C')
        {
            at_Cli_Con_Flag   = 1;
            memset(buffer,'\0',SIZE);
        }

        //如果用op指令开灯,cl指令关灯
        //检测返回的字符是否为:op和:cl开始,:op时打开灯,:cl时关灯
        if(buffer[0]==':' && buffer[1]=='o' && buffer[2]=='p')  
        {
            LED1 = 0;
            memset(buffer,'\0',SIZE);
        }
        if(buffer[0]==':' && buffer[1]=='c' && buffer[2]=='l')
        {
            LED1 = 1;
            memset(buffer,'\0',SIZE);
        }
        //防止指针越界
        if(i == SIZE)
        {
            i = 0;
        }
    }
		
	
	if(TI);
		
}

4.6调试方法

  调试方法依旧用白盒调试,调试思路和1.7一样。

结束语

  很高兴您能看到这里,点个赞再走呗。谢谢您啦!!!

你可能感兴趣的:(学习嵌入式笔记,智能手机,电脑,51单片机,嵌入式硬件,c语言,学习)