关于单片机连接ESP8266模块截取其回显内容

发布者:星光小狐狸最新更新时间:2018-11-21 来源: eefocus关键字:单片机连接  ESP8266模块  回显内容 手机看文章 扫描二维码
随时随地手机看文章

1,首先,ESP使用串口,跟51单片机通信,控制端可以使用手机,但是,51单片机和手机不在一个档次,那么在51单片机上需要分析操作。


2,ESP8266在接收或者发送数据时,会向串口发送回显内容,也就是提示信息,提示接收到了什么,发送了什么,所以,在单片机上做字符串的分析截取很重要,不然手机和单片机的通信质量大大下降,前期的wifi小车写项目的时候,这个问题困扰了我很久,后来进度过慢,我就折衷的使用了分析一个字符的方法,对小车进行控制,但是这样的处理方式很差。


3,前阵子终于把wifi小车做完了,虽然只是简单的行进和lcd显示以及避障,但也不能继续做下去了,需要去学新东西了,在这之前我需要把ESP用的完善了才能安心学下一步的东西,也为以后的项目铺了路。


分析思路:


1,首先uart串口的初始化不再详述,学习过就可以初始化成功。


2,然后,在串口的中断服务函数中,用temp承接SBUF中的回显数据,再在中断服务函数中立即做判断处理,该存的存,该舍弃的跳过,而且在中断服务函数中不能做延时较长的动作,所以只能使用令人头疼的标志位。


3,那么如何辨别什么时候是一整句的回显呢?因为回显并不回显\0,最多也只有\r\n(回车换行),那么如何判断什么时候开始接收一句话的第一个字符呢?我现在使用的方法是,把\n作为接收一句回显的开始,把\r作为接收一句回显的结束。这个过程通过设置标志位实现,较为简单。


0,CONNECT


+IPD,0,1:y


对应十六进制:30 2C 43 4F 4E 4E 45 43 54 0D 0A 0D 0A 2B 49 50 44 2C 30 2C 31 3A 79


\r \n \r \n


1_副本.png

2_副本.png

3_副本.png


以上是回显的模板,可以根据这些内容理解出使用\r\n判断起始终止位置比较有效。


4,其次,现在比较重要的就是获取手机发来的数据,也就是+IPD,0,3:abc(0:客户连接号,3:字符串长度)这样的回显句子,需要截取下来,并存在单片机中,供其他函数使用,那么解析这个字符串就是在动态的过程中做的,所以时效性需要很高,需要立即分析完成并且处理完毕,不能先存下来再判断,因为没有字符串结束符,结束标志完全靠着:前面的3,也就是字符串长度来判断,这里连\r都没有用,只能动态的判断分析获取。


5,以下为串口中断服务函数51程序


//中断服务函数,用于软复位


void uart_isr() interrupt 4


{


//loc用来对ret_msg全局变量给偏移,用来组装一个字符串


static unsigned char i = 0;


unsigned char temp;


ES = 0;


temp = SBUF;//temp不能被改变,因为软复位需要用到


/*ESP8266截取字符串部分*/


if(temp == '\n')//开始符


{


Rev_status = BEGIN;//设置开始接收


}


else if(temp == '\r')//结束符


{


Rev_status = END;//设置结束接收


}


else//出来\r\n以外的字符


{


/************************************************/


//专门用来接收IPD和CIFSR,结束接收时要把Rev_Str_status置为无效,再次进入下面的循环,检测第一个字符


if(Rev_Str_status == BEGIN)


{


if((str_rev_flag == END) &&(temp != ':') && (str_len_flag == BEGIN))//开始接收字符串长度


{


str_len = str_len * 10 + (temp - '0');


}


//为了充分保证,只有一种情况,并且进入一次,采用多个flag


if((str_rev_flag == END) &&(First_dou_flag == OK) && (temp == ',') && (client_num_flag == BEGIN) && (str_len_flag == END))//再一次接收到了逗号,开始接收字符串长度


{


str_len_flag = BEGIN;


client_num_flag = END;


}


//第一个逗号来临,进入,以后不再进入


if((str_rev_flag == END) &&(First_dou_flag == NO) && (temp == ',') && (client_num_flag == END))//逗号来临


{


client_num_flag = BEGIN;


First_dou_flag = OK;//是第一个逗号


}


//开始接收用户连接号


if((str_rev_flag == END) && (temp != ',') && (client_num_flag == BEGIN))


{


client_num = client_num * 10 + (temp - '0');


}


//开始接收字符串


if(str_rev_flag == BEGIN)


{


//保存字符串到全局变量中,以便后面输出


Get_str[Get_str_loc] = temp;


Get_str_loc ++;


//如果字符串的长度和刚刚接收到的指明字符串长度相同,则不再接收,做收尾工作


if(Get_str_loc == str_len)


{


Get_str[Get_str_loc] = '\0';


Str_Ready = OK;//设置标志位,说明我已经接收到了一个整的字符串了,可以进行操作了。


Rev_Str_status = END;//清空接收字符串标志位,使得可以再次进入下面switch循环


client_num_flag = END;//清空接收client_num标志位


str_len_flag = END;//清空接收str_len字符串长度标志位


str_rev_flag = END;//清空接收真正字符串标志位


First_dou_flag = NO;//清空区分第几个逗号的标志位


}


}


if(temp == ':')//要是开始了:,那么后面开始接收字符长度为str_len的字符串长度


{


str_rev_flag = BEGIN;


}


}


/************************************************/


/************************************************/


//要在接收字符串的标志位无效,并且接收状态位有效的时候才做


if((Rev_Str_status == END) && (Rev_status == BEGIN))


{


//检测到第一个以后,立刻置接收标志位无效暂时不接收


switch(temp)


{


case '+'://要么接收到+IPD 要么接收到 +CIFSR


{


Rev_Str_status = BEGIN;//开始接收,暂时不进入这个switch循环


Rev_status = END;


break;


}


case 'E'://发送失败,回显ERROR


{


Send_flag = NO;


Rev_status = END;


break;


}


case 'S'://发送成功,回显SEND OK


{


Send_flag = OK;


Rev_status = END;


break;


}


default:


{


Rev_status = END;


break;


}


}


}


}


//软复位时使用


if(0x7f == temp)//special for Doflye


{


i ++;


if(10 == i)


{


i = 0;


ISP_CONTR = 0xe0;


}


}


else


{


i = 0;


}


RI = 0;


ES = 1;


}


6,由于是在动态过程中做的,那么判断和标志位是无可奈何的选择,这里就需要逻辑搞清楚,虽然上面的程序我也是比较晕的,但是凭着感觉写出来,在进行一点一点调试,最后还是能够稳定的实现的。算法方面我还需要加强。


7,还有一个就是要善用sprintf它可以把你需要显示的数字转化为对应的字符串。注意:最好使用int型。


8.下面是整个模块函数及使用范例


/********************使用示例**********************************/


// /*测试ESP8266,目的:获得回显信息*/


// #include


// #include "delay.h"


// #include "WifiESP8266.h"


// #include "lcd.h"


// #include "uart.h"


// #include "delay.h"


// #include


// #include


// extern bit Ok_flag;


// extern bit Str_Ready;


// extern bit Rev_Str_status;


// extern bit str_rev_flag;


// extern bit flag;


// extern unsigned char Get_str[40];


// extern int client_num;


// extern int str_len;


// void main()


// {


// unsigned char temp_buf[16] = "Tmp:26 Hum:56";


// int i = 0;


// uart_init();


//


// lcd_init();


// lcd_clean();


// delay_ms(500);


//


// WifiESP8266_Init("ZTLTest","0123456789","8000");


//


// while(1)


// {


// if(OK == SendStrToClint(temp_buf,0,strlen(temp_buf)))


// //发送给连接号为0的客户,hhh,三个字节长度


// {


// lcd_clean();


// lcd_write_str(1,1,"SEND OK");


// }


// else


// {


// lcd_clean();


// lcd_write_str(1,1,"ERROR");


// }


//


// if(check_revStr() == OK)//也可以改成while在某个函数体中做


// {


// /*************写对获取的字符串的操作**************/


// sprintf(temp_buf,"%d %d %s\0",client_num,str_len,Get_str);


// lcd_write_str(0,0,temp_buf);


// /*****************************************/


//


//


// /*****************测试接收成功后,回复信息,可不加******************/


// // if(OK == SendStrToClint(Get_str,0,strlen(Get_str)))


// // //发送给连接号为0的客户,hhh,三个字节长度


// // {


// // lcd_clean();


// // lcd_write_str(1,1,"SEND OK");


// // }


// // else


// // {


// // lcd_clean();


// // lcd_write_str(1,1,"ERROR");


// // }


// /******************************************************/


//


//


// /**************************必须要加!********************************/


// clean_flag();//调用wifi模块中的清空函数


// /*******************************************************/


// }


//


//


// }


// }


/************************************************************/


/*


wifi模块ESP8266模块测试函数


作者:张天乐


起始时间:2016/1/19


功能:完成基本的连接等功能


修改时间:2016/1/28


功能:能够实现区分哪个客户端发来的什么数据


*/


#include


#include "WifiESP8266.h"


#include "uart.h"


#include "lcd.h"


#include "delay.h"


#include


#include


//接收状态默认为结束


bit Rev_status = END;//接收状态位


bit Rev_Str_status = END;//接收字符串状态位


bit Send_flag = NO;//发送信息到手机状态位


bit OK_flag = NO;//成功状态位


bit Str_Ready = NO;//数据准备好状态位


bit First_dou_flag = NO;//是不是第一个逗号


//获取的字符串内容


unsigned char Get_str[40];


unsigned char Get_str_loc = 0;


//客户连接号,以及字符串长度


int client_num = 0;


int str_len = 0;


bit client_num_flag = END;


bit str_len_flag = END;


bit str_rev_flag = END;


//检测是否接收到了数据,供其他函数调用,如果接收到了数据,那么,就供其他函数提取全局变量Get_str


//在其他函数接收完以后,还要调用清空函数,清空标志位,以便下一次使用


bit check_revStr()


{


if(Str_Ready == OK)


{


return OK;


}


return NO;


}


void clean_flag()


{


//清空操作


memset(Get_str,0,sizeof(Get_str));


client_num = 0;


str_len = 0;


Get_str_loc = 0;//清空一部分全局变量,以便下一次操作,Get_str要在外面函数接收完再清空


Str_Ready = NO;//清空接收数据准备好标志位


}


//发送字符串给给客户端连接号为num的客户端,内容为参数str


//str:发送内容,str_len:发送的字节数,client_num:客户端连接号,注意:参数均为字符串形式!


bit SendStrToClint(unsigned char *str,int client_num,int str_len)//有待加入字符串解析,用于判断是否发送成功


{


//用于拼接AT指令的buffer


unsigned char AT_temp[30] = {0};


//拼接成: "AT+CIPSEND=client_num,str_len\r\n" 设置发送,=后面第一个参数是客户连接号即client_num,第二个是需要发送的字节数


sprintf(AT_temp,"AT+CIPSEND=%d,%d\r\n",client_num,str_len);


uart_sendstr(AT_temp);//将封装完的AT指令发送出去


delay_ms(50);


//发送需要发送的字节


uart_sendstr(str);


delay_s(1);


//经过一秒以后,查看是否有发送成功标志位,要是发送成功了,那么就置Send_flag为有效


if(Send_flag == NO)


{


return NO;


}


else


{


//发送完成以后,还要清空标志位为无效,以便下次使用


Send_flag = NO;


return OK;


}


}


//wifi模块的初始化函数 wifi名字和wifi密码和端口名称,IP名固定为192.168.4.1


void WifiESP8266_Init(unsigned char *name,unsigned char *password,unsigned char *port)


{


//用于拼接AT字符串命令


unsigned char AT_tempBuf[50] = {0};


//发送AT指令,设置wifi模式等


uart_sendstr("AT+RST\r\n");//重启


delay_s(1);


uart_sendstr("AT+CWMODE=2\r\n");//设置为AP模式,wifi模块当做路由器


delay_s(1);


//设置wifi名称和密码


sprintf(AT_tempBuf,"AT+CWSAP=\"%s\",\"%s\",11,4\r\n",name,password);


uart_sendstr(AT_tempBuf);


memset(AT_tempBuf,0,sizeof(AT_tempBuf));//用完清空


delay_s(1);


uart_sendstr("AT+RST\r\n");//重启


delay_s(1);


uart_sendstr("AT+CIPMUX=1\r\n");//设为多路


delay_s(1);


//开始拼接带有端口号的字符串


sprintf(AT_tempBuf,"AT+CIPSERVER=1,%s\r\n",port);


uart_sendstr(AT_tempBuf);//打开服务,需要拼接


memset(AT_tempBuf,0,sizeof(AT_tempBuf));//用完清空


delay_s(1);


}


//中断服务函数,用于软复位


void uart_isr() interrupt 4


{


//loc用来对ret_msg全局变量给偏移,用来组装一个字符串


static unsigned char i = 0;


unsigned char temp;


ES = 0;


temp = SBUF;//temp不能被改变,因为软复位需要用到


/*ESP8266截取字符串部分*/


if(temp == '\n')//开始符


{


Rev_status = BEGIN;//设置开始接收


}


else if(temp == '\r')//结束符


{


Rev_status = END;//设置结束接收


}


else//出来\r\n以外的字符


{


/************************************************/


//专门用来接收IPD和CIFSR,结束接收时要把Rev_Str_status置为无效,再次进入下面的循环,检测第一个字符


if(Rev_Str_status == BEGIN)


{


if((str_rev_flag == END) &&(temp != ':') && (str_len_flag == BEGIN))//开始接收字符串长度


{


str_len = str_len * 10 + (temp - '0');


}


//为了充分保证,只有一种情况,并且进入一次,采用多个flag


if((str_rev_flag == END) &&(First_dou_flag == OK) && (temp == ',') && (client_num_flag == BEGIN) && (str_len_flag == END))//再一次接收到了逗号,开始接收字符串长度


{


str_len_flag = BEGIN;


client_num_flag = END;


}


//第一个逗号来临,进入,以后不再进入


if((str_rev_flag == END) &&(First_dou_flag == NO) && (temp == ',') && (client_num_flag == END))//逗号来临


{


client_num_flag = BEGIN;


First_dou_flag = OK;//是第一个逗号


}


//开始接收用户连接号


if((str_rev_flag == END) && (temp != ',') && (client_num_flag == BEGIN))


{


client_num = client_num * 10 + (temp - '0');


}


//开始接收字符串


if(str_rev_flag == BEGIN)


{


//保存字符串到全局变量中,以便后面输出


Get_str[Get_str_loc] = temp;


Get_str_loc ++;


//如果字符串的长度和刚刚接收到的指明字符串长度相同,则不再接收,做收尾工作


if(Get_str_loc == str_len)


{


Get_str[Get_str_loc] = '\0';


Str_Ready = OK;//设置标志位,说明我已经接收到了一个整的字符串了,可以进行操作了。


Rev_Str_status = END;//清空接收字符串标志位,使得可以再次进入下面switch循环


client_num_flag = END;//清空接收client_num标志位


str_len_flag = END;//清空接收str_len字符串长度标志位


str_rev_flag = END;//清空接收真正字符串标志位


First_dou_flag = NO;//清空区分第几个逗号的标志位


}


}


if(temp == ':')//要是开始了:,那么后面开始接收字符长度为str_len的字符串长度


{


str_rev_flag = BEGIN;


}


}


/************************************************/


/************************************************/


//要在接收字符串的标志位无效,并且接收状态位有效的时候才做


if((Rev_Str_status == END) && (Rev_status == BEGIN))


{


//检测到第一个以后,立刻置接收标志位无效暂时不接收


switch(temp)


{


case '+'://要么接收到+IPD 要么接收到 +CIFSR


{


Rev_Str_status = BEGIN;//开始接收,暂时不进入这个switch循环


Rev_status = END;


break;


}


case 'E'://发送失败,回显ERROR


{


Send_flag = NO;


Rev_status = END;


break;


}


case 'S'://发送成功,回显SEND OK


{


Send_flag = OK;


Rev_status = END;


break;


}


default:


{


Rev_status = END;


break;


}


}


}


}


//软复位时使用


if(0x7f == temp)//special for Doflye


{


\i ++;


if(10 == i)


{


i = 0;


ISP_CONTR = 0xe0;


}


}


else


{

i = 0;


}


RI = 0;


ES = 1;


}


最后,还是有点缺陷的是,没有很好的完成安卓的客户端,只能发送字符串给单片机,但是不能将单片机发来的数据用socket在手机上显示出来,安卓是个弱项,但是socket通信还是需要好好学学,网络编程后续学习,对应安卓客户端我也会尝试写出来。


关键字:单片机连接  ESP8266模块  回显内容 引用地址:关于单片机连接ESP8266模块截取其回显内容

上一篇:使用stm8单片机的“外部计数”TIMx_ETR测脉冲的软件配置问题
下一篇:实现蓝牙HC-05、06与单片机的连接及与手机通信

推荐阅读最新更新时间:2024-03-16 16:17

LCD显示器与PIC16F877单片机连接
一.引言     液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。而美国Microchip公司生产的PIC系列单片机系用精简指令集(RISC),哈佛总线结构、2级流水线取指令方式,具有实用、低价、指令集小、简单易学、低功耗、高速度、体积小、功能强而逐渐成为8位单片机的新潮流。这里以JHD161A液晶模块与PIC16F877的连接来介绍它的使用方法。 二.JHD161A  LCD显示器及其与PIC16F877单片机的连接     JHD161A液晶模块是一种用5x7点阵图形来显示字符的液晶显示器,是武汉博控科技有限公司生产的1行16个字符的LCD显示模块
[单片机]
LCD显示器与PIC16F877<font color='red'>单片机</font><font color='red'>连接</font>
MCU应用系统与Internet连接的一种新技术
摘要:介绍一种新型的智能网络接口芯片PS2000及其应用。PS2000是Webchip网络接口系列中的重要成员,通过它可以实现智能装置与PC机平台的网关接口,使智能装置通过PS2000上网十分方便,设计者在设计这样的系统时无须熟知网络协议。 关键词:网络接口芯片 Internet Webchip PS2000 MCU Gateway 前言 今天为们生活在一个信息时代,Internet已经成为信息社会的重要组成部分,Internet技术将深入到日常生活和工作所用到的电子设备中。我们知道,Internet技术得以迅速发展的主要推动力之一是标准十分成熟的PC工业。无论是PC机的硬件平台,还是软件操作系统都高度标准化,上网的操作方式也不同小
[嵌入式]
着重USB连接 MCU厂商加快革新步伐
  如今带USB接口的8位MCU的全球市场规模庞大,约占8位MCU市场中的10%。并且发展趋势是全速USB正取代低速USB。   随着USB(通用串行总线)规范的不断完善,USB的应用领域在不断拓展,从PC外设、消费电子和工业设备等简直是不胜枚举。嵌入式系统生产商的问题已经不是在产品中实现USB,而是如何最佳地将USB性能集成到产品中去,以大大地提升产品的连接性能。看好这轮“连接”热潮,半导体厂商不仅纷纷在其MCU中植入USB连接功能,并着眼于未来需求突出兼容性。   创新功能注入活力   如今带USB接口的8位MCU的全球市场规模庞大,约占8位MCU市场中的10%。并且发展趋势是闪存正取代ROM(只读存储器)和OTP(
[单片机]
意法半导体新微控制器为物联网开发人员扩大设备连接选择
中国,2018年3月13日——意法半导体STM32软件生态系统新增一个Sigfox™软件包,可简化物联网设备开发,提升物联网设备与远距离低功耗无线网络连接的灵活性。 这款新X-CUBE-SFOX软件包可直接与意法半导体 B-L072Z-LRWAN1探索套件 配套使用,实际上, I-CUBE-LRWAN 嵌入式软件已经让该套件具有 LoRa™ 连接功能。现在,开发人员可以从这两款低功耗广域物联网(LPWAN)技术中任选一种用于同一硬件,开发一款使用其中一个协议或两个协议交替使用的物联网产品。该探索套件的产品亮点包括搭载STM32L072微控制器的Murata CMWX1ZZABZ-091模块、Semtech 的sub-GHz射
[物联网]
意法半导体新<font color='red'>微控制器</font>为物联网开发人员扩大设备<font color='red'>连接</font>选择
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved