Author:果果小师弟 电子信息专业在读研究生
有一点思考,有一点想法,有一点理性!
定个小小目标,努力成为习惯!在最美的年华遇见更好的自己!
个人主页的地址为:
果果小师弟的个人小站
-
STM32物联网实战教程(一)—ESP8266的AT指令集详解
-
STM32物联网实战教程(二)—MQTT协议简介
-
STM32物联网实战教程(三)—MQTT协议产品和设备
-
STM32物联网实战教程(四)—MQTT协议Connect控制报文
-
STM32物联网实战教程(五)—MQTT订阅主题和订阅确认
-
STM32物联网实战教程(六)—MQTT协议取消订阅和取消订阅确认
-
STM32物联网实战教程(七)—MQTT协议发布消息和发布确认
-
STM32物联网实战教程(八)—Android studio新建一个项目
-
一、ESP8266 01S简介
-
二、ESP8266刷固件
-
三、 AT指令控制 ESP8266 模组
-
1. 测试模块是否正常(AT)
-
2. 开启/关闭回显(ATE1/ATE0)
-
3. 设置AP模式及AP参数(AT+CWMODE ,AT+CWSAP_DEF)
-
4. 设置为Station 模式(AT +CWMODE=1,AT +CWJAP)
-
5. 使用TCP实现局域网内的设备通信
-
5.1建立TCP连接(AT+CIPSTART)
-
5.2开启透传传输(AT+CIPMODE=1)
-
6.使用SmartConfig为设备配网
-
四、单片机实现TCP通信
介绍各种网络通信协议之前我们必须保证硬件设备先连接到网络才行,联网的方式有很多种,比如通过网线联网、GPRS 联网(SIM 流量业务)、或者家中 WIFI 路由器联网。这常用的三种方式只不过是硬件层不同而已,其内置的都是 TCP/IP 网络协议,其中
最方便、成本最低的联网方式是 WIFI 联网
。
WIFI 射频芯片的供应商市面上有很多,常见的比如乐鑫,博通,瑞昱,德州仪器(TI)、庆科等。
ESP8266 的特点的就是价格便宜、资料齐全,支持 SDK 开发和 AT 开发
。其中 SDK 开发可以省去外部的单片机,我们直接使用乐鑫提供的库函数来编写程序,使得成本降低,而
AT 开发是指使用外部单片机通过串口和 WIFI 模块通信
,其通信的指令中包含 AT 前缀,这种开发方式虽然成本比 SDK 开发高,但是开发周期短。
除了合宙的 WIFI 模组之外,用的比较多的还有乐鑫官方推出的 ESP-WROOM-02和安信可的 ESP8266 系列模组(常用的比如 ESP-12F)以及劢领的 M0M10xP0 系列(使用的是澜起的 WIFI芯片),M0M10xP0 模块的亮点是可以通过网页对其进行设置并支持 FTP 功能,这样可以很方便的对单片机进行在线升级。
一、ESP8266 01S简介
使用 AT 功能之前,模块内必须有 AT 的固件,每个模块的生产厂商都会对乐鑫官方的 AT 固件做一些修改和删减,但是其最核心的 AT 指令功能都是相同的。我们买的ESP8826模块一般都有刷好的固件,所以不用自己刷固件。
ESP-01S WiFi 模块是一款低功耗高性价比的嵌入式无线网络控制模块。可满足智能电网、楼宇自动化、安防、智能家居、远程医疗等物联网应用的需求。 该模块核心处理器 ESP8266 在较小尺寸封装中集成了业界领先的 Tensilica L106 超低功耗 32 位微型 MCU,带有 16 位精简模式,主频支持 80 MHz 和 160 MHz,支持 RTOS,集成 Wi-Fi MAC/ B/RF/PA/LNA,板载天线。 该模块支持标准的 IEEE802.11 b/g/n 协议,完整的 TCP/IP 协议栈。用户可以使用该模块为现有的设备添加联网功能,也可以构建独立的网络控制器。
(1) 模块供电电压为直流3.3V、电流为500mA以上;
(2) Wi-Fi模块IO最大输出电流为12mA;
(3) Wi-Fi模块NRST管脚低电平有效;EN使能管脚高电平有效;
(4) Wi-Fi模块进入升级模式:GPIO0处于低电平,然后模块复位上电;Wi-Fi模块进入正常工作模式: GPIO0处于高电平,模块复位上电。
(5)Wi-Fi模块的RXD接外部MCU的TXD,Wi-Fi模块的TXD接外部MCU的RXD;
二、ESP8266刷固件
刷固件可以用杜邦线,也可以用刷固件的模块(淘宝上几块钱就可以买到),如下图:
三、 AT指令控制 ESP8266 模组
乐鑫官方的 AT 指令有将近 100 条,但常用的就十几条,理解起来也非常简单,现在举例一些常用指令,并使用这些指令一步一步的通过 TCP 连接到远程的服务器实现收发数据,更多 AT 指令可以查阅《ESP8266 AT 指令集手册》。
总结 AT 指令的构成就是,每条指令要以
AT
开始,后面跟要查询(读)或者要设置(写)的参数,例如查询 WIFI 模式对应的指令为
AT+CWMODE?
,设置 WIFI 模式为
AT+CWMODE=3
。另外要求的回车换行符结尾是说要在待发送的数据后面追加\r\n,即十六进制的 0x0D 0x0A。
注意
:
在使用串口调试助手发送AT 指令时,只需要在待发送指令后面加回车即可,大家可以勾选“ 按十六进制发送”,观察数据后面是否追加了 0x0D 0x0A 。 如果在数据后面添加\ \r r\ \n n 则会将其作为字符 发送而非换行符。
1. 测试模块是否正常(AT)
该指令通常在开机后查询模块是否正常启动,如果回复 OK 则表示为正常启动。
2. 开启/关闭回显(ATE1/ATE0)
从上图可以看出,我们发送了一个
AT
,模块回复了
AT OK
,即模块将发送过来的指令原封不动的先复述了一遍后接着发送有效回复,我们称这种复述为回显,关闭回显(发送
ATE0
)后如再次发送
AT
,则只回复
OK
。如下图:
3. 设置AP模式及AP参数(AT+CWMODE ,AT+CWSAP_DEF)
WIFI 模式有两种,一种叫 AP 模式,一种叫 Station 模式,
AP 就是我们平时所说的热点
,如 WIFI 路由器,开了热点的手机,或者是公共热点等,这些 AP 设备可以允许其他设备(如手机,笔记本电脑等)输入热点名和密码(也可不设置密码)后接入,
Station 则是前面说的连接 AP 的设备,如:手机,笔记本电脑等
,ESP8266 还有第三种模式:AP+Station,即:将 AP 和 Station 的功能合二为一,但是应用的场景不多,这里不做展示。当 ESP8266 设置为 AP 模式时,其他设备可以接入该热点,最多支持 4 台 Station 设备接入。AP 模式也是 ESP8266 默认的模式。设置 ESP8266 流程如下:
1.首先发送AT+CWMODE?查询模块当前处于哪一种模式,如下图可以知道AT+CWMODE=2也就是热点模式。
2.然后我们发送
AT+CWMODE=2
,让模块处于热点模式下,同时我们的电脑上也会显示热点名称。
3.我们现在自定义设置我们ESP8266的热点名和密码,来看看我们电脑能不能连接我们所设置的好的ESP8266模块。
-
1、设置WIFI模式为AP模式,也就是充当热点模式(
AT+CWMODE=2
)
另:
AT+CWMODE=1
为 Station 模式,
AT+CWMODE=3
位 AP+Station 模式
-
2、设置AP热点属性(
AT+CWSAP=AT+CWSAP_DEF="ESP8266-XSD","12345678",5,3
)
其含义为:热点名为
ESP8266-XSD
,密码为
12345678
,使用
通道5
,
加密方式为 WPA2_PSK
,这里的通道对应的就是不同的射频频率,如果同一空间内存在相同通道的 WIFI 信号,将会产生干扰,影响上网质量,因此可以设置通道来避免这种干扰,常用的通道有 1、6、11,因为这三个通道互不产生干扰。设置效果如下图:
连接数量可以限制 Station 设备的接入数量,广播或者不广播 SSID 就是指是否隐藏热点名,使热点更加安全。另外
AT+CWSAP=AT+CWSAP_DEF
表示设置的参数会存储的 flash,还有另外一个类似指令
AT+CWSAP=AT+CWSAP_ CUR
,该条指令表示设置的参数重启后失效,即不保存到 flash 中。其他的 AT 指令也有类似的后缀。
4. 设置为Station 模式(AT +CWMODE=1,AT +CWJAP)
该模式是平时应用最多的模式,因为物联网设备需要连接到家中路由才可以接入外网,此时设备就作为 Station 连接到 AP 热点。设置 Station 并连接 AP 流程如下:
-
1.设置 WIFI 模式为 Station(
AT+CWMODE=1
)
-
2.连接到家中路由器(
AT+CWJAP="liuyao","liuyao1001"
)
下图为连接过程的串口输出:
这时候我们进入家中的路由器就能看到我们的ESP8266模块连接到了家中的路由器。如果想要断开连接,可以使用
AT+CWQAP
,就可以断开ESP8266与路由器的连接。
现在我们的ESP8266已经与家中的路由器连接上了,现在我们如果想获取连接的这个ESP8266的IP可以使用
AT+CIPSTA?
指令,返回的是路由器分配给 ESP8266 的局域网IP以及网关地址和子网掩码 。
5. 使用TCP实现局域网内的设备通信
5.1建立TCP连接(AT+CIPSTART)
TCP实现局域网内的设备通信时先要让ESP8266连接到家中的热点。该条指令可以指定建立连接的协议类型,通常使用的有两种:TCP和UDP。我们先打开网络调试助手,并将其设置为
TCP Server
端,具体设置如下:
接着发送AT指令建立 TCP 连接:
AT+CIPSTART="TCP","192.168.0.103",8080
,成功连接会提示CONNECT,接着使用发送指令:
AT+CIPSEND=14
,其中14是发送数据的长度,该指令发送完成后,接收窗口会显示
>
,我们接着在发送窗口发送
I m TCP Client
,TCP Server 端会收到该信息,接着再通过 TCP Server 发送
I m TCP Server
,串口接收端会打印 Client 收到的数据。
下面就是ESP8266连接当前环境的热点,与服务器建立TCP连接,传输数据的过程和动画演示(所有的字符和标点必须是英文)。
-
1.设置WIFI 模式为 Station:
AT+CWMODE=1
-
2.连接到家中路由器:
AT+CWJAP="liuyao","liuyao1001"
-
3.发送AT指令建立 TCP 连接:
AT+CIPSTART="TCP","192.168.0.103",8080
-
4.提示发送数据长度为14:
AT+CIPSEND=14
(返回>)
-
5.串口调试助手发送:
I m TCP Client
(返回
Recv 14 bytea SEND OK
)
-
6.网络调试助手发送:
I m TCP Server
(串口调试助手收到
+IPD,21:hello I m TCP Server!
)
这一步很多人可能很懵,不知道为啥要这样做,你这个搞的串口调试助手还有网络调试助手还有啥TCP Server到底是啥意思啊?
哈哈,我相信很多初学者学到这里也不是很清楚。我这里简单说一下,我们的用ESP8266是不是要让它连到家中的网啊,那在这里我们的网络调试助手的TCP Server就是我们要连接的网络。有人又要说了,我要连家中路由器的网啊,为啥要连网络调试助手的网啊?这是因为如果你连家中的网,请问你如何给你家的路由器发送数据啊!你怎么知道路由器接收到了数据啊!路由器又咋给你发送数据啊!你又咋接收数据啊!我们这里用网络调试助手的目的就是让网络调试助手来代替路由器局域网。TCP Server就是服务端的意思也是就是服务器。至于为啥用串口调试助手我就不用说了吧,只有你在串口助手上调试好了,我们才用单片机的串口结合ESP8266共同代替客服端,也就不需要调试助手了。
所以说我们一定要在串口调试助手上把相关的数据调通了,把原理过程搞懂了之后我们再去搞单片机程序,再去搭建你的服务器而不是用网络调试助手代替了。
怎么样现在明白了吧
!
5.2开启透传传输(AT+CIPMODE=1)
前面在使用 TCP 进行数据发送时,在每次发送数据之前都要指定发送数据的长度,而且在接收到数据之后,还会有+IPD,< len>的前缀,这样很不方便进行数据的处理,因此我们可以使用
AT+CIPMODE=1
指令开启透传模式,开启透传模式后只需要在第一次发送数据时使用
ATD +CIPSEND
指令来告诉ESP8266开始透传发送,随后我们直接发送想要的数据即可,在接收到数据时,也没有了+IPD,< len >前缀。
下面就是ESP8266连接当前环境的热点,与服务器建立TCP连接,开启透传模式传输数据的过程和动画演示(所有的字符和标点必须是英文)。
-
1.设置WIFI 模式为 Station:
AT+CWMODE=1
-
2.连接到家中路由器:
AT+CWJAP="liuyao","liuyao1001"
-
3.发送AT指令建立 TCP 连接:
AT+CIPSTART="TCP","192.168.0.103",8080
-
4.开启透传模式:
AT+CIPMODE=1
(返回
ok
)
-
5.开始透传发送:
AT+CIPSEND
(返回
>
)
-
6.串口调试助手发送:
hello I m TCP Client!
(网络调试助手收到
hello I m TCP Client!
)
-
7.网络调试助手发送:
hello I m TCP Server!
(串口调试助手收到
>hello I m TCP Server!
)
如果想要退出透传发送模式,先发送
+++
(0x2B 0x2B 0x2B),
注意没有换行符
,接着使用
AT+CIPMODE=0
(
有换行符
)指令退出透传模式,恢复到默认传输模式。如果不退出透传模式,那么在透传模式下就不能发送AT指令了,它会默认为字符串发送。
注意
:在
非透传模式下
,客户端每次向服务端发送数据之前都要先发送
AT+CIPSEND=<len>
来告诉服务端我接下来要发送数据的长度,否则在发送之后会返回
EEROR
。
注意:在
透传模式下
,客户端每次向服务端发送数据之前不需要发送
AT+CIPSEND=<len>
来告诉服务端我接下来要发送数据的长度。在设置好透传模式(即发送了
AT+CIPMODE=1
和
AT+CIPSEND
)后,直接发送数据就可以了。
在
非透传模式下和透传模式下
。只有客服端向服务端发送数据之前需要先发送最对应的命令,然后再发送数据。而服务端向客户端发送数据之前不需要向客户端先发送任何命令,直接就是发送数据。另外,所有AT指令(
除了退出透传的+++指令
)和数据在发送时都需要勾选
发送新行
或
AT指令自动回车
,也就是说命令和数据发送之前都需要
回车换行
,否则不能发送成功。
6.使用SmartConfig为设备配网
前面使用了AT+CWJAP指令来主动连接家中的 WIFI,但是在大多数的物联网产品中,缺少输入 WIFI 密码的输入设备,如:键盘,更不能将程序交给用户去修改家中的 WIFI 热点名和密码,在真正的项目开发中使用最多的方法就是通过一颗按键来使设备进入某种模式,并使用手机将当前 WIFI 的密码告知该设备来实现 WIFI 配网,这种模式就是SmartConfig(不同厂商叫法不一,但功能相近),在该模式下ESP8266会监听指定端口的UDP广播包,如果收到符合规定格式的广播包后会对其进行解析并获得WIFI的SSID 和PWD,然后自动连接获取到的 WIFI 热点,从而实现WIFI 配网。
智能配网需要三个设备:家中的
路由器、WIFI模块、手机
。处于station模式,手机连接好家中的wifi。 具体的这个工作的原理是:我们需要将wifi配置为station模式。因为这个模式默认的是ap模式,然后我们要保证手机连接到家中的路由器热点。手机上面的第一行是我们手机此时连接的这个热点名,下面第一行需要用户去手动的输入路由器热点对应的密码,下面会有一个按键就写着叫配网(连接),那么当我们点击这个配网之后,手机则会以UDP的这种传输的方式。向某个端口号或某个IP地址当中去广播。广播内容是厂商自己封装的一个数据帧结构,当然广播的时候就不用去指定具体的IP地址,因为每个模组可能默认是不同的。只要指定账号当我按下配网的这个按钮之后,此时它会UDP广播的形式向外连续的去发送一串儿厂商约定好的一个数据帧结构,比如说前面对应的是什么厂商的这个ID呀,然后后面跟的是这个热点名,后面跟着的是这个热点密码等等,当然我们也可以对它进行一些加密处理,如果此时我们通过按下这个。用点上面的某个按键,比如说是配置了我们这个wifi模组,进入了smartconfig这个配网模式。这个时候wifi模块会处于一个监听的状态。比如udp的协议监听50000端口上面这个数据。如果我收到了这一块儿有效的数据,那么他会将这里面有用的热点名和密码摘出来,然后使用类似透传模式这种功能,内部的将它连接到指定的热点上面,就实现了一键配网的过程。
我们可以使用 AT+CWSTARTSMART=< type>指令来设置 ESP8266使其进入SmartConfig模式,其中的type是指不同的配网协议,如下图:
其中的 ESP-TOUCH 是乐鑫官方的配网协议,AirKiss 是微信推出的配网协议,由于微信拥有庞大的用户群体,所以很多厂商和产品都支持 AirKiss 协议配网。下面我们使用配网 AT指令使ESP8266 进入配网状态,此时大家扫描关注下方微信公众号,该公众号是后面例程要接入的云平台的厂商公众号,里面有 WIFI 配网功能,使用的是 AirKiss 协议:
在公众号中点击WIFI配网按钮,接着进入了设备配网界面(此时要保证手机连接到63WIFI路由器),点击立即链接并输入 WIFI 密码,最后点击连接即可,效果如下:
-
1.设置WIFI 模式为 Station:
AT+CWMODE=1
-
2.连接到家中路由器:
AT+CWJAP="liuyao","liuyao1001"
-
3.使用SmartConfig为设备配网:
AT+CWSTARTSMART=3
ESP8266 检测到了配网协议类型以及WIFI的SSID和PWD并自动连接到 WIFI 路由器,此时 ESP8266会将这些WIFI信息存储到flash中,并且在设备每次重启时会自动联网。需要注意的是配网完成之后要记得停止配网模式(AT+CWSTOPSMART),释放ESP8266的内存。但是我们在后续的例程中并没有使用SmartConfig进行配网,而是使用手动连接,其目的是让大家理解 WIFI 联网的过程。
四、单片机实现TCP通信
上面我们说到了ESP8266的AT指令集的使用,我们只是单单说了指令没有说在STM32上怎么把这些命令转换成函数,这一章就是要将那每一个指令集换成函数来实现ESP8266与网页端调试助手的数据互相发送,学习这一章的主要目的就是要明白如何将AT指令集换成函数通过STM32的USART1将数据发送到网页端。
所需材料:STM32F103C8T6核心板、ESP8266-01S模块、一台电脑。
程序源码框架:正点原子例程
-
使用STM32F103C8T6的UART2和ESP8266模块进行AT通信,实现连接无线路由器功能以及TCP、UDP 通信;
-
STM32 采集传感器数据并定时上传至服务器;
-
根据服务器下发的指令控制两个继电器的工作状态。
我们就是要实现单片机+ESP8266将DHT11的温湿度信息上传到服务器,效果如下:
实现设备连接远程服务器的流程为:
-
设置 ESP8266 连接 AP 热点使其正常上网
-
设置 ESP8266 连接远程/局域网TCP或UDP服务器
-
将采集到的传感器数据发送到服务器
-
根据服务器传输过来的控制指令做出相应动作,如控制 LED 和继电器
/******************************************************************
* 文件:esp8266.c
* 功能:实现TCP、UDP通信相关函数
*******************************************************************/
#include "esp8266.h"
char TXBuffer[TXBUFFER_LEN] = {0}; //网络通信数据发送缓冲
char RXBuffer[RXBUFFER_LEN] = {0}; //网络通信数据接收缓冲
* 功能:查找字符串中是否包含另一个字符串
* 参数:
* dest:待查找目标字符串
* src:待查找内容
* retry_cn:查询超时时间
* 返回值:查找结果,非0为查找成功,0为失败
* 说明:
* 当发出一个AT指令后,需要一段时间等待ESP8266回复,因此就需要等待一段时间,
* 这个时间通常是几百ms(除了连接服务器和AP指令),本程序一般指令通常等待
* 2S,耗时的连接AP和服务器的设置等待为8S,其实花不了那么多时间,但如果发生超时
* 就一定可以判断是通信问题
static u8 findStr(char* dest,char* src,u16 retry_cn)
u16 retry = retry_cn; //超时时间
u8 result_flag = 0; //查找结果
while(strstr(dest,src)==0 && --retry!=0)//等待串口接收完毕或超时退出
delay_ms(10);
if(retry==0) //如果超时则有问题,此时返回0
return 0;
result_flag = 1; //执行到这里说明一切正常, 表示查找成功
if(result_flag)
return 1;
}else
return 0;
* 功能:初始化ESP8266
* 参数:None
* 返回值:初始化结果,非0为初始化成功,0为失败
u8 ESP8266_Init(void)
sendString(USART2,"+++"); //退出透传
delay_ms(500);
sendString(USART2,"AT+RST\r\n"); //重启ESP8266
delay_ms(500);
if(checkESP8266()==0) //使用AT指令检查ESP8266是否存在
return 0;
memset(RXBuffer,0,RXBUFFER_LEN); //清空接收缓冲
sendString(USART2,"ATE0\r\n"); //关闭回显
if(findStr(RXBuffer,"OK",200)==0) //设置不成功
return 0;
return 1; //设置成功
* 功能:恢复出厂设置
* 参数:None
* 返回值:None
* 说明:此时ESP8266中的用户设置将全部丢失回复成出厂状态
void restoreESP8266(void)
sendString(USART2,"+++"); //退出透传
delay_ms(500);
sendString(USART2,"AT+RESTORE\r\n");//恢复出厂
NVIC_SystemReset(); //同时重启单片机
* 功能:检查ESP8266是否正常
* 参数:None
* 返回值:ESP8266返回状态
* 非0 ESP8266正常
* 0 ESP8266有问题
u8 checkESP8266(void)
memset(RXBuffer,0,RXBUFFER_LEN); //清空接收缓冲
sendString(USART2,"AT\r\n"); //发送AT握手指令
if(findStr(RXBuffer,"OK",200)!=0)//ESP8266正常
return 1;
}else //ESP8266不正常
return 0;
* 功能:连接热点
* 参数:
* ssid:热点名
* pwd:热点密码
* 返回值:
* 连接结果,非0连接成功,0连接失败
* 说明:
* 失败的原因有以下几种(UART通信和ESP8266正常情况下)
* 1. WIFI名和密码不正确
* 2. 路由器连接设备太多,未能给ESP8266分配IP
u8 connectAP(char * ssid,char* pwd)
memset(RXBuffer,0,RXBUFFER_LEN);
sendString(USART2,"AT+CWMODE?\r\n"); //查询此时WIFI工作模式
if(findStr(RXBuffer,"CWMODE:1",200)==0) //如果此时不是MODE1模式,即不是STATION模式
memset(RXBuffer,0,RXBUFFER_LEN);
sendString(USART2,"AT+CWMODE_CUR=1\r\n"); //设置为STATION模式
if(findStr(RXBuffer,"OK",200)==0)
return 0;
memset(TXBuffer,0,RXBUFFER_LEN); //清空发送缓冲
memset(RXBuffer,0,RXBUFFER_LEN); //清空接收缓冲
sprintf(TXBuffer,"AT+CWJAP_CUR=\"%s\",\"%s\"\r\n",ssid,pwd);//连接目标AP
sendString(USART2,TXBuffer);
if(findStr(RXBuffer,"OK",800)!=0) //连接成功且分配到IP
return 1;
* 功能:使用指定协议(TCP/UDP)连接到服务器
* 参数:
* mode:协议类型 "TCP","UDP"
* ip:目标服务器IP
* port:目标是服务器端口号
* 返回值:
* 连接结果,非0连接成功,0连接失败
* 说明:
* 失败的原因有以下几种(UART通信和ESP8266正常情况下)
* 1. 远程服务器IP和端口号有误
* 2. 未连接AP
* 3. 服务器端禁止添加(一般不会发生)
u8 connectServer(char* mode,char*ip,u16 port)
memset(RXBuffer,0,RXBUFFER_LEN);
memset(TXBuffer,0,RXBUFFER_LEN);
sendString(USART2,"+++"); //多次连接需退出透传
delay_ms(500);
/*格式化待发送AT指令*/
sprintf(TXBuffer,"AT+CIPSTART=\"%s\",\"%s\",%d\r\n",mode,ip,port);
sendString(USART2,TXBuffer);
if(findStr(RXBuffer,"CONNECT",800)!=0)
memset(RXBuffer,0,RXBUFFER_LEN);
sendString(USART2,"AT+CIPMODE=1\r\n"); //设置为透传模式
if(findStr(RXBuffer,"OK",200)!=0)
memset(RXBuffer,0,RXBUFFER_LEN);
sendString(USART2,"AT+CIPSEND\r\n");//开始处于透传发送状态
if(findStr(RXBuffer,">",200)!=0)
return 1;
}else
return 0;
}else
return 0;
}else
return 0;
* 功能:主动和服务器断开连接
* 参数:None
* 返回值:
* 连接结果,非0断开成功,0断开失败
u8 disconnectServer(void)
sendString(USART2,"+++"); //退出透传
delay_ms(500);
memset(RXBuffer,0,RXBUFFER_LEN);
sendString(USART2,"AT+CIPCLOSE\r\n");//关闭链接
if(findStr(RXBuffer,"CLOSED",200)!=0)//操作成功,和服务器成功断开
return 1;
}else
return 0;
* 功能:透传模式下的数据发送函数
* 参数:
* buffer:待发送数据
* 返回值:None
void sendBuffertoServer(char *buffer)
memset(RXBuffer,0,RXBUFFER_LEN);
sendString(USART2,buffer);
* 功能:处理服务器发回来的控制指令
* 参数:None
* 返回值:None
void processServerBuffer(void)
u8 i = 0;
/*LED状态控制*/
if(strstr(RXBuffer,"LED_ON"))
LED=1;
}else if(strstr(RXBuffer,"LED_OFF"))
LED=0;
}else if(strstr(RXBuffer,"LED_S"))
/*继电器1状态控制*/
if(strstr(RXBuffer,"RELAY1_CLOSE"))
setRelay(RELAY1,RELAY_CLOSE);
}else if(strstr(RXBuffer,"RELAY1_OPEN"))
setRelay(RELAY1,RELAY_OPEN);
}else
/*继电器2状态控制*/
if(strstr(RXBuffer,"RELAY2_CLOSE"))
setRelay(RELAY2,RELAY_CLOSE);
}else if(strstr(RXBuffer,"RELAY2_OPEN"))
setRelay(RELAY2,RELAY_OPEN);
}else
/*只在接收控制指令时才清空,这样可避免接收AT指令时导致失败*/
if(i!=0)
memset(RXBuffer,0,RXBUFFER_LEN);
/******************************************************************
* 文件:esp8266.h
* 功能:声明TCP、UDP通信相关函数
*******************************************************************/
#ifndef __ESP8266_H
#define __ESP8266_H
#include "sys.h"
/*连接AP宏定义*/
#define SSID "liuyao"//你家中的WIFI名
#define PWD "liuyao1001"//你家中的WIFI密码
/*连接服务器宏定义*/
#define TCP "TCP"
#define UDP "UDP"
/*服务器的IP和端口号每次刷新都会改变,记得要修改这里*/
#define IP "180.97.81.180"//这个就是网页端服务器的IP地址
#define PORT 56177 //这个就是网页端服务器的端口号
/*发送接收缓冲区长度宏定义*/
#define TXBUFFER_LEN 50
#define RXBUFFER_LEN 30
u8 checkESP8266(void);
u8 ESP8266_Init(void);
void restoreESP8266(void);
u8 connectAP(char * ssid,char * pwd);
u8 connectServer(char* mode,char* ip,u16 port);
void sendBuffertoServer(char* buffer);
void processServerBuffer(void);
u8 disconnectServer(void);
#endif
#include "sys.h"
extern char TXBuffer[TXBUFFER_LEN];
int main(void)
u8 i = 0;
u8 key_value;
u16 DHT11_data; //存储DHT11传感器采集数据
u16 Volt; //存储ADC数据
/*初始化各外设*/
delay_init(); //延时函数初始化
UART2_Init();
LED_Init();
Key_Init();
Adc_Init();
Relay_Init();
DHT11_Init();
OLED_Init() ;
OLED_Clear() ;
ESP8266_Init();
/*打印ESP8266启动信息到OLED*/
if(ESP8266_Init()!=0)
OLED_ShowString(0,0,"init ok!",16);
}else
OLED_ShowString(0,0,"init error!",16);
if(connectAP(SSID,PWD)!=0)
OLED_ShowString(0,2,"con ap ok",16);
}else
OLED_ShowString(0,2,"con ap error!",16);
if(connectServer(TCP,IP,PORT)!=0)
OLED_ShowString(0,4,"con server ok!",16);
}else
OLED_ShowString(0,4,"con server error!",16);
delay_ms(1000);//让数据保持一段时间
OLED_Clear() ;
First_show();
while (1)
if(++i>=200) //每隔2S左右采集一次 建议采集间隔最小不要小于2S
i = 0;
/*采集传感器数据*/
DHT11_data = readDHT11();
Volt = getConvValueAve();
/*输出传感器数据到服务器*/
memset(TXBuffer,0,TXBUFFER_LEN);
sprintf(TXBuffer,"Hum:%d,Temp:%d,Adc:%d\n",DHT11_data>>8,DHT11_data&0x00FF,Volt);
sendBuffertoServer(TXBuffer);
/*同时显示在OLED上*/
OLED_ShowNumber(40,2,DHT11_data>>8,2,16);
OLED_ShowNumber(40,4,DHT11_data&0x00FF,2,16);
OLED_ShowNumber(40,6,Volt,2,16);
key_value = getKeyValue(KEY_RELEASE);
/*UP键按下恢复出厂*/
if(key_value==KEY_UP)
restoreESP8266();
/*DOWN键按下断开TCP连接*/
if(key_value==KEY_DOWN)
disconnectServer();
delay_ms(10);//基础延时
关注公众号:果果小师弟,后台回复:ESP8266TCP。获取程序源码及原理图。
好书不厌百回读,熟读自知其中意。将学习成为习惯,用知识改变命运,用博客见证成长,用行动证明努力。
easyui显示架构图 easyui框架简介
EasyUI就是一套基础JQuery的前端框架(简化ajax,jquery,css样式,布局)。可以使用其中的组件进行布局以及用来做后台的管理界面。
EasyUI是一个前端开发的框架,其将常用的页面开发使用的组件进行了封装,前端开发人员只需将EasyUI的资源导入项目后使用即可,快速提升开发效率。
iOS 拍照后获取图片路劲 苹果读取照片位置
今天突然想到微信朋友圈发照片,涉及个人隐私的地理位置是否外泄。由于iphone拍照的照片都会带有地理位置等信息。我们先来实现怎么读取里面的安全信息。然后再来分析#import "ViewController.h"
#import <ImageIO/ImageIO.h>
#import <AssetsLibrary/AssetsLibrary.h>
@interface Vi