从零开始制作一个基于STM32和ESP8266-01S的智能时钟(3)ESP8266-01S模块(上)

这篇具有很好参考价值的文章主要介绍了从零开始制作一个基于STM32和ESP8266-01S的智能时钟(3)ESP8266-01S模块(上)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

提示:这里可以添加本文要记录的大概内容:之前在忙着,现在继续补充完整,然后这次的ESP-01S的典型应用图是没有连接RST引脚的,但是我的项目是用到了RST引脚的,所以需要使用跳线连接一下RST引脚。

本项目需要基础的stm32单片机知识,这里我推荐
链接:https://www.bilibili.com/video/BV1th411z7sn?p=1&vd_source=e9ab6ae9ee7c74bb73c9334f2da0a743
如果不想看那么多,看到4-2 OLED显示屏就差不多。我使用的是他的OLED基本例程。


提示:以下是本篇文章正文内容,下面案例可供参考

一、ESP8266-01S模块

ESP-01S 是由安信可科技开发的 Wi-Fi 模块,该模块核心处理器 ESP8266 在较小尺寸封装中集成了业界领先的 Tensilica L106 超低功耗 32 位微型 MCU,带有 16 位精简模式,主频支持 80 MHz 和 160 MHz,支持 RTOS,集成 Wi-Fi MAC/ BB/RF/PA/LNA。
ESP-01S Wi-Fi 模块支持标准的 IEEE802.11 b/g/n 协议,完整的 TCP/IP 协议栈。用户可以使用该模块为现有的设备添加联网功能,也可以构建独立的网络控制器。
ESP8266 拥有完整的且自成体系的 Wi-Fi 网络功能,既能够独立应用,也可以作为从机搭载于其他主机 MCU 运行。

这里我截一些规格书和说明书上面一些图给大家参考一下。可以去这个网址找规格书和说明书:https://docs.ai-thinker.com/esp8266/docs

esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

我们可以看到ESP8266-01S模块是支持UART通信的,通信的波特率默认为115200bps。一般来说,EN和RST引脚需要外接一个上拉电阻,但是看原理图我们可以发现,ESP-01S内部已经上拉这两个引脚了,不需要我们操心,所以我们按照下面的电路图将ESP-01S连接到STM32上即可。但是我的代码中还使用了RST引脚作为复位引脚,所以还需要连接RST引脚到STM32上。
RST引脚因为上拉电阻的作用默认高电平,低电平有效,所以我们想要复位一次的话,只需要使用STM32拉低RST引脚,再将它拉高回到默认高电平状态。
esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

还有使用说明书上有个注意事项,不清楚这是为什么。但是我测试的时候发现如果接到ESP-01S的3.3V和GND不稳定会出现无法通信的情况,并且ESP-01S会发热变得烫手,所以测试的过程请随时注意ESP-01S的状态避免发生意外,注意、注意、注意(一般是刚上电的时候)。解决办法是可以将3.3V和GND重新连接,直到可以通信。或者想办法找个稳定的3.3V和GND
esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

二、ESP8266-01S模块使用方法

1.AT指令

ESP8266 系列模组出厂时已默认内置 AT 固件,且默认波特率为 115200。我们只需要将ESP8266-01S模块通过UART连接到STM32上,然后使用STM32发送AT指令的方式将可以控制ESP8266-01S模块执行各种功能。

我这里就只介绍我用到的AT指令,其他的你们可以去网上找,也可以去看说明书。网址:https://www.cnblogs.com/milton/p/14718010.html
还有AT指令需要加回车符和换行符"\r\n".

  1. AT :测试AT开发模式启动
  2. AT+CWMODE=1 :设置WIFI应用模式,1–Station模式,2–AP模式,3–AP兼Station模式。 AP指ESP8266 作为接入点,station指ESP8266 作为客户端
  3. AT+CWJAP=“WIFI名字”,“WIFI密码” :设置 ESP8266 Station 需连接的 AP。
  4. AT+CIPSTART=“TCP”,“59.82.34.102”,80 :ESP8266 设备作为 TCP client 连接到服务器,这里高德地图的远端 IP 地址为59.82.34.102,远端端口号为 80。
  5. AT+CIPMODE=1 :设置透传模式(即可以一直发送。透传模式传输时,如果连接断开,ESP8266 会不停尝试重连,此时单独输⼊ +++【不用加回车换行符】 退出透传,则停⽌重连;普通传输模式则不会重连,提示连接断开。)(一般来说普通传输模式交换一次数据后就会断开TCP连接,如果想要继续通信需要重新进行TCP连接,所以为了方便一直获取天气和时间信息,这里选择透传模式)
  6. AT+CIPSEND : ESP8266 设备向服务器发送数据,在透传模式时,进⼊透传模式发送数据,每包最大 2048 字节,或者每包数据以 20 ms 间隔区分。(进入发送数据模式后,AT指令无效,如需退出发送数据模式,发送 +++【不用加回车换行符】,然后就可以使用AT指令)。

2.代码分析

首先是串口外设初始化函数和串口发送功能函数,这里使用重定义print函数的方法实现串口print函数打印,但是实际测试过程发现UsartPrintf()发送大量数据时,会出现数据丢失的情况,(应该是因为UsartPrintfBuf[296]设置的数组长度不够,如果想要发送大量数据可以试着修改一下这个数组长度),所以发送大量字符串数据时可以使用Usart_SendString()函数。然后本项目使用串口1进行调试,所以需要对串口1进行初始化,但是串口1并不进行接收数据操作,所以可以注释掉串口1的接收中断使能和接收中断函数,效果不会改变。项目使用串口2和ESP-01S连接通信,使用串口2发送AT指令和接收ESP-01S返回的数据,为了方便这里将串口2的接收中断函数放到ESP-01S操作文件中。

/*
************************************************************
*	函数名称:	UsartPrintf
*
*	函数功能:	格式化打印
*
*	入口参数:	USARTx:串口组
*				fmt:不定长参
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...)
{

	unsigned char UsartPrintfBuf[296];		/*接收输入变量数组,如果数组不够大,可以修改一下*/
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化
	va_end(ap);
	
	while(*pStr != 0)
	{
		USART_SendData(USARTx, *pStr++);
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
	}

}
/*
************************************************************
*	函数名称:	Usart_SendString
*
*	函数功能:	串口数据发送
*
*	入口参数:	USARTx:串口组
*				str:要发送的数据
*				len:数据长度
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{

	unsigned short count = 0;
	
	for(; count < len; count++)
	{
		USART_SendData(USARTx, *str++);									//发送数据
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);		//等待发送完成
	}

}

还有介绍一下USART_FLAG_TXE标志位,USART_FLAG_TXE是数据寄存器空标志位。串口发送数据的方式是数据先从MCU内部的CPU到数据寄存器,再到移位寄存器,然后由移位寄存器发送到TX线上。而使用USART_SendData()函数就是将数据从CPU转移到数据寄存器,这个过程是非常迅速的,而数据从数据寄存器到移位寄存器的过程相对比较缓慢,因为移位寄存器要一位位地发送数据,而数据寄存器需要等移位寄存器变空才能发送数据到移位寄存器,所以为了避免数据从CPU转移到数据寄存器的过程太快而导致数据覆盖产生数据丢失的问题,需要设置一个while循环等USART_FLAG_TXE变为1,即数据寄存器变空。

esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

经过这个项目,我对于串口中断有不一样的理解。我一开始以为串口接收到一帧数据(指多bit数据)会一直处于接收中断函数中,不会中途跳回主函数中。但经过测试,事实上,串口接收到一帧数据时当然会先进入中断函数接收1bit数据,然而就算后面还有几bit数据没接收完,它还是会跳回主函数执行一小段时间,然后再回到中断函数接收下一bit数据,循环这个过程,直到接收完成。
esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

所以如果接收不定长数据并且没有特定结束符,我们无法在主函数中直接判断什么时候接收完成。但是有位大佬使用了一个叹为观止的方法实现了判断接收不定长数据的完成。就是程序中的ESP8266_WaitRecive()函数,调用函数时会比较上一次接收到的数据量和这一次接收到的数据量进行比较。如果不相同,证明程序进入了接收中断函数使得接收到的数据量发生了变化,然后将发生变化后的数据量赋值给上一次接收到的数据量。如果相同,证明程序没有再进入中断函数,即已经接收完成。我们只需要循环调用这个函数即可判断这一帧数据是否接收完成。

#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志

unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;		/*esp8266_cnt为当前接收到的数据数量,esp8266_cntPre为上一次接收到的数据数量*/

//==========================================================
//	函数名称:	ESP8266_WaitRecive
//
//	函数功能:	判断是否接收完成
//
//	入口参数:	无
//
//	返回参数:	REV_OK-接收完成		REV_WAIT-接收超时未完成
//
//	说明:		循环调用检测是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)
{

	if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕
	{
//		esp8266_cnt = 0;							//清0接收计数,注释掉是为了接收几帧数据
		
		return REV_OK;								//返回接收完成标志
	}
		
	esp8266_cntPre = esp8266_cnt;					//置为相同
	
	return REV_WAIT;								//返回接收未完成标志

}

ESP8266_SendCmd()函数就使用到了上面提到的判断一帧数据的方法。这个函数是用来发送AT指令给ESP8266的,并且通过串口1返回ESP8266的响应数据,通过这个数据即可判断和调试ESP8266是否正确执行指令。

串口1的返回如下:
esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

ESP8266的实际返回如下:
esp8266-01s wifi时钟,stm32,单片机,嵌入式硬件

其实ESP8266实际返回的数据中有几个数据返回是几帧数据返回的,如图中的

[15:51:47.291]收←◆AT+CWJAP=“DSKrurudo”,“12359680” WIFI DISCONNECT

[15:51:47.510]收←◆WIFI CONNECTED

[15:51:48.525]收←◆WIFI GOT IP
OK

这是连接wifi完成后返回的几帧数据,而ESP8266_SendCmd()函数里面通过ESP8266_WaitRecive()判断一帧数据接收完后,继续通过判断响应数据中的"OK"判断响应数据包是否接收完,即接收几帧的数据包,就可以将响应数据包接收完整,然后通过串口1打印出来。

//==========================================================
//	函数名称:	ESP8266_SendCmd
//
//	函数功能:	发送命令
//
//	入口参数:	cmd:命令
//				res:需要检查的返回指令
//
//	返回参数:	0-成功	1-失败
//
//	说明:		
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
	
	unsigned char timeOut = 200;

	Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
	
	while(timeOut--)
	{
		if(ESP8266_WaitRecive() == REV_OK)							//如果收到1帧数据
		{
			if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词
			{
				UsartPrintf(USART_DEBUG, "%s", esp8266_buf);		//通过调试串口将接收到的返回指令显示出来以便判断
				ESP8266_Clear();									//清空缓存
				
				return 0;		//数据包接收完成跳出循环
			}
		}
		Delay_ms(10);		//通过延时循环等待数据包接收完成
	}
	
	return 1;
}

3.完整代码

usart.h

#ifndef _USART_H_
#define _USART_H_


#include "stm32f10x.h"


#define USART_DEBUG		USART1		//调试打印所使用的串口组


void Usart1_Init(unsigned int baud);

void Usart2_Init(unsigned int baud);

void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len);

void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...);

#endif

usart.c

//硬件驱动
#include "usart.h"
#include "delay.h"

//C库
#include <stdarg.h>
#include <string.h>
#include <stdio.h>


/*
************************************************************
*	函数名称:	Usart1_Init
*
*	函数功能:	串口1初始化
*
*	入口参数:	baud:设定的波特率
*
*	返回参数:	无
*
*	说明:		TX-PA9		RX-PA10
************************************************************
*/
void Usart1_Init(unsigned int baud)
{

	GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
//	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	
	//PA9	TXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_9;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	//PA10	RXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_10;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	usartInitStruct.USART_BaudRate = baud;
	usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//无硬件流控
	usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和发送
	usartInitStruct.USART_Parity = USART_Parity_No;									//无校验
	usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位数据位
	USART_Init(USART1, &usartInitStruct);
	
	USART_Cmd(USART1, ENABLE);														//使能串口
	
//	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);									//使能接收中断
//	
//	nvicInitStruct.NVIC_IRQChannel = USART1_IRQn;
//	nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
//	nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
//	nvicInitStruct.NVIC_IRQChannelSubPriority = 2;
//	NVIC_Init(&nvicInitStruct);

}

/*
************************************************************
*	函数名称:	Usart2_Init
*
*	函数功能:	串口2初始化
*
*	入口参数:	baud:设定的波特率
*
*	返回参数:	无
*
*	说明:		TX-PA2		RX-PA3
************************************************************
*/
void Usart2_Init(unsigned int baud)
{

	GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	//PA2	TXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_2;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	//PA3	RXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_3;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	usartInitStruct.USART_BaudRate = baud;
	usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//无硬件流控
	usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和发送
	usartInitStruct.USART_Parity = USART_Parity_No;									//无校验
	usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位数据位
	USART_Init(USART2, &usartInitStruct);
	
	USART_Cmd(USART2, ENABLE);														//使能串口
	
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);									//使能接收中断
	
	nvicInitStruct.NVIC_IRQChannel = USART2_IRQn;
	nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
	nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	nvicInitStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&nvicInitStruct);

}

/*
************************************************************
*	函数名称:	Usart_SendString
*
*	函数功能:	串口数据发送
*
*	入口参数:	USARTx:串口组
*				str:要发送的数据
*				len:数据长度
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{

	unsigned short count = 0;
	
	for(; count < len; count++)
	{
		USART_SendData(USARTx, *str++);									//发送数据
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);		//等待发送完成
	}

}

/*
************************************************************
*	函数名称:	UsartPrintf
*
*	函数功能:	格式化打印
*
*	入口参数:	USARTx:串口组
*				fmt:不定长参
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...)
{

	unsigned char UsartPrintfBuf[296];		/*接收输入变量数组,如果数组不够大,可以修改一下*/
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化
	va_end(ap);
	
	while(*pStr != 0)
	{
		USART_SendData(USARTx, *pStr++);
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
	}

}

///*
//************************************************************
//*	函数名称:	USART1_IRQHandler
//*
//*	函数功能:	串口1收发中断
//*
//*	入口参数:	无
//*
//*	返回参数:	无
//*
//*	说明:		
//************************************************************
//*/
//void USART1_IRQHandler(void)
//{

//	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
//	{
//		USART_ClearFlag(USART1, USART_FLAG_RXNE);
//	}

//}

esp8266.h

#ifndef _ESP8266_H_
#define _ESP8266_H_





#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志


void ESP8266_Init(void);

void ESP8266_Clear(void);

void ESP8266_SendData(unsigned char *data, unsigned short len);

unsigned char *ESP8266_GetIPD(unsigned short timeOut);
_Bool ESP8266_SendCmd(char *cmd, char *res);
_Bool ESP8266_WaitRecive(void);


#endif

esp8266.c

//单片机头文件
#include "stm32f10x.h"

//网络设备驱动
#include "esp8266.h"

//硬件驱动
#include "Delay.h"
#include "usart.h"

//C库
#include <string.h>
#include <stdio.h>



#define ESP8266_WIFI_INFO		"AT+CWJAP=\"DSKrurudo\",\"12359680\"\r\n"			/*连接wifi的AT指令*/

//#define ESP8266_ONENET_INFO		"AT+CIPSTART=\"TCP\",\"broker.emqx.io\",1883\r\n"

#define ESP8266_TIANQI_INFO		"AT+CIPSTART=\"TCP\",\"59.82.34.102\",80\r\n"		/*连接高德地图TCP的AT指令*/

unsigned char esp8266_buf[360];			/*接收ESP-01s的返回数据数组*/
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;		/*esp8266_cnt为当前接收到的数据数量,esp8266_cntPre为上一次接收到的数据数量*/

//unsigned char send_data[]="GET\r\n";

//==========================================================
//	函数名称:	ESP8266_Clear
//
//	函数功能:	清空缓存
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_Clear(void)
{

	memset(esp8266_buf, 0, sizeof(esp8266_buf));
	esp8266_cnt = 0;

}

//==========================================================
//	函数名称:	ESP8266_WaitRecive
//
//	函数功能:	判断是否接收完成
//
//	入口参数:	无
//
//	返回参数:	REV_OK-接收完成		REV_WAIT-接收超时未完成
//
//	说明:		循环调用检测是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)
{

	if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕
	{
//		esp8266_cnt = 0;							//清0接收计数,注释掉是为了接收几帧数据
		
		return REV_OK;								//返回接收完成标志
	}
		
	esp8266_cntPre = esp8266_cnt;					//置为相同
	
	return REV_WAIT;								//返回接收未完成标志

}

//==========================================================
//	函数名称:	ESP8266_SendCmd
//
//	函数功能:	发送命令
//
//	入口参数:	cmd:命令
//				res:需要检查的返回指令
//
//	返回参数:	0-成功	1-失败
//
//	说明:		
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
	
	unsigned char timeOut = 200;

	Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
	
	while(timeOut--)
	{
		
		if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据
		{
			if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词
			{
				UsartPrintf(USART_DEBUG, "%s", esp8266_buf);		//通过调试串口将接收到的返回指令显示出来以便判断
				ESP8266_Clear();									//清空缓存
				
				return 0;
			}
			
		}
		
		Delay_ms(10);
		
	}
	
	return 1;

}

//==========================================================
//	函数名称:	ESP8266_SendData
//
//	函数功能:	发送数据
//
//	入口参数:	data:数据
//				len:长度
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_SendData(unsigned char *data, unsigned short len)
{

	char cmdBuf[32];
	
	ESP8266_Clear();								//清空接收缓存
	sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);		//发送命令
	if(!ESP8266_SendCmd(cmdBuf, ">"))				//收到‘>’时可以发送数据
	{
		UsartPrintf(USART_DEBUG, "you are real");
		Usart_SendString(USART2, data, len);		//发送设备连接请求数据
	}

}

//==========================================================
//	函数名称:	ESP8266_GetIPD
//
//	函数功能:	获取平台返回的数据
//
//	入口参数:	等待的时间(乘以10ms)
//
//	返回参数:	平台返回的原始数据
//
//	说明:		不同网络设备返回的格式不同,需要去调试
//				如ESP8266的返回格式为	"+IPD,x:yyy"	x代表数据长度,yyy是数据内容
//==========================================================
unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{

	char *ptrIPD = NULL;
	
	do
	{
		if(ESP8266_WaitRecive() == REV_OK)								//如果接收完成
		{
			ptrIPD = strstr((char *)esp8266_buf, "IPD,");				//搜索“IPD”头
			if(ptrIPD == NULL)											//如果没找到,可能是IPD头的延迟,还是需要等待一会,但不会超过设定的时间
			{
				UsartPrintf(USART_DEBUG, "\"IPD\" not found\r\n");
			}
			else
			{
				ptrIPD = strchr(ptrIPD, ':');							//找到':'
				if(ptrIPD != NULL)
				{
					ptrIPD++;
					return (unsigned char *)(ptrIPD);
				}
				else
					return NULL;
				
			}
		}
		
		Delay_ms(5);													//延时等待
	} while(timeOut--);
	
	return NULL;														//超时还未找到,返回空指针

}

//==========================================================
//	函数名称:	ESP8266_Init
//
//	函数功能:	初始化ESP8266
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_Init(void)
{
	
	GPIO_InitTypeDef GPIO_Initure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

	//ESP8266复位引脚
	GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_Initure.GPIO_Pin = GPIO_Pin_14;					//GPIOC14-复位
	GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_Initure);
	
	GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_RESET);		//拉低GPIOC14使能RST引脚
	Delay_ms(500);
	GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_SET);			//拉高GPIOC14回到默认状态
	Delay_ms(500);
	
	ESP8266_Clear();		//清空上一次的接收缓存
	Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "0. AT\r\n");
	ESP8266_SendCmd(" AT\r\n", "OK");		//测试AT
	Delay_ms(500);
	
//	UsartPrintf(USART_DEBUG, "1. RST0\r\n");
//	ESP8266_SendCmd("AT+RST\r\n", "OK");
//	UsartPrintf(USART_DEBUG, "1. RST1\r\n");
//		Delay_ms(500);
//	ESP8266_SendCmd("AT+CIPCLOSE\r\n", "OK");
//	UsartPrintf(USART_DEBUG, "1. RST2\r\n");
//		Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "1. CWMODE\r\n");
	ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK");		//设置ESP8266作为客户端
	Delay_ms(500);
	
//	UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\r\n");
//	ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK");
//		Delay_ms(500);
//		Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "2. CWJAP\r\n");
	ESP8266_SendCmd(ESP8266_WIFI_INFO, "OK");		//连接wifi
	Delay_ms(500);
	
//	UsartPrintf(USART_DEBUG, "5. CIPSTART\r\n");
//	while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
//		Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "3. CIPSTART\r\n");
	ESP8266_SendCmd(ESP8266_TIANQI_INFO, "OK");		//连接到服务器
	Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "4. AT+CIPMODE=1\r\n");
	ESP8266_SendCmd("AT+CIPMODE=1\r\n", "OK");		//设置透传模式
	Delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "5. AT+CIPSEND\r\n");
	ESP8266_SendCmd("AT+CIPSEND\r\n", ">");		//开启数据传输模式
	Delay_ms(500);

//	UsartPrintf(USART_DEBUG, "6.AT+CIPSEND=5\r\n");
//	ESP8266_SendCmd("AT+CIPSEND=6\r\n", ">");
//		Delay_ms(500);
	
//	UsartPrintf(USART_DEBUG, "8. GET\r\n");
//	ESP8266_SendData(send_data, 6);

	
//	if(ESP8266_GetIPD(0) != NULL)
//	{
//		UsartPrintf(USART_DEBUG, "noNULL\r\n");
//	}

}

//==========================================================
//	函数名称:	USART2_IRQHandler

//	函数功能:	串口2收发中断

//	入口参数:	无

//	返回参数:	无

//	说明:		
//==========================================================
void USART2_IRQHandler(void)
{

	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //串口2接收中断
	{
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆,如果接收超过了接收数组的容量,从第一位开始覆盖接收数组
		esp8266_buf[esp8266_cnt++] = USART_ReceiveData(USART2);		//将接收到的数据放到接收数组里
		USART_ClearFlag(USART2, USART_FLAG_RXNE);			//清除中断标志位
	}

}

总结

这次介绍了一下ESP8266的使用方法和注意事项,还有我对串口中断的了解。因为太长了,所以获取和处理天气、时间信息就放在下一文章中。文章来源地址https://www.toymoban.com/news/detail-780578.html

到了这里,关于从零开始制作一个基于STM32和ESP8266-01S的智能时钟(3)ESP8266-01S模块(上)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零开始制作STM32F103RCT6小车(一)

            仅以此系列给实验室的学弟学妹作为小车制作教程来使用,后续的内容我会在这个暑假陆续更新出来,本篇的内容是新建一个适用于STM32F103RCT6的工程         接下来的操作几乎是基于STM32F1xx系列的固件库,这里我给大家列出链接 STM32F1xx系列固件库               

    2023年04月08日
    浏览(63)
  • 基于STM32+FreeRtos+ESP8266+MQTT连接阿里云

    实现通过stm32f103c8t6+操作系统(freertos)读取dht12温湿度传感器的数据,采用ESP8266连接网络,经过MQTT协议连接阿里云IOT,进行数据的传输,以及服务器发送数据控制LED的亮灭,包括消息的发布和订阅等操作,完成云端和设备端的通讯。 首先,我们使用MQTT.fx模拟器,通过模拟的

    2024年02月06日
    浏览(51)
  • STM32系列(HAL库)——使用ESP8266-01S物联网模块连接Onenet云平台上报DHT11温湿度

    本篇主要讲解如何使用ESP8266-01S物联网模块连接Onenet云平台,并上报DHT11模块的温湿度数据。本文单片机主控采用STM32F405RGT6,使用其他主控的话基本要求有2个串口,一个串口用于调试使用,另一个用于ESP模块通讯。 1.软件 CubeMX Keil5 串口调试助手 Onenet云平台账户 2.硬件 STM32开

    2024年02月02日
    浏览(80)
  • 学习素材之USART篇——通过使用STM32与ESP8266(esp-01s)连接阿里云系列操作来了解USART协议和寄存器操作

    目录 USART详解 一、串口通讯协议简介 串口通讯的物理层 串口通讯的协议层 二、STM32 的 USART 简介 USART功能概述 功能引脚 三、与USART有关的寄存器 USART寄存器地址映像  四、USART寄存器描述 1、USART状态控制器(USART_SR) 2、数据寄存器(USART_DR) 3、波特比率寄存器(USART_BRR) 4、控

    2024年02月16日
    浏览(51)
  • 从零开始,我的第一个物联网平台搭建好了,ESP8266+DHT11+阿里云平台+IOT StudioWEB应用开发,实现网页实时查看设备上报的信息,控制开关

        记录下自己做的第一个物联网项目,真正从零开始,断断续续花了2个月时间看各种视频,网站学习有关物联网的知识,期间碰到过好多问题,没有人指导,都得靠自己慢慢研究,有时会很迷茫,没有方向,但还得坚持下去,当经过自己的努力解决一个个问题时,会很兴奋

    2024年01月19日
    浏览(94)
  • 基于STM32、OV2640及ESP8266的无线图传

            本文利用STM32F407单片机、OV2640摄像机模块以及ESP8266 WIFI模块,并基于C#编写的TCP上位机服务,来实现图像的无线传输。         本文受启发于博客:ESP8266+STM32F407+OV7670实现图片传输,在此感谢该文作者。与该文不同的是,本文采用的摄像机模块是0V2640,传输的

    2024年01月18日
    浏览(56)
  • 基于STM32设计的智慧农业管理系统(ESP8266+腾讯云微信小程序)

    基于STM32设计的智慧农业控制系统(ESP8266+腾讯云微信小程序) 随着人们对食品安全和生态环境的日益重视,智慧农业逐渐成为一个备受关注的领域。智能化管理可以提高农业生产效率,减少资源浪费,改善生态环境。因此,基于物联网技术的智慧农业管理系统越来越受到农民和

    2024年02月08日
    浏览(47)
  • ESP8266 模块简易驱动程序 -- 基于 STM32F103 及原子云固件实现云功能

    本简易驱动程序是基于 正点原子 的ESP8266模块,主要用于实现连接 原子云 的功能。MCU选用的是 STM32F103ZET6 注:原子云固件添加了 AT+ATKCLDSTA 和 AT+ATKCLDCLS 两条指令 用于连接正点原子自家的原子云平台,原厂的AT指令不受任何影响 本程序主要实现了如下功能: 设定工作模式 连

    2023年04月23日
    浏览(46)
  • 从零开始手搓一个STM32与机智云的小项目——硬件介绍

    由于在嵌入式学习笔记那个系列的所有开发都是用的寄存器,而实际工作中使用更多的还是库函数,为了完善一下,笔者就想着先整个基础库笔记,但是又像之前那样记录又觉着太麻烦了,所以就打算自己做个板子,综合使用一下之前的东西,然后围绕着这个板子的硬件来做

    2024年02月06日
    浏览(47)
  • 提供最全面最详细的ESP32从零开始搭建一个物联网平台教程(从最基本的配网和内建WEB服务器开始到自已搭建一个MQTT服务器)

    目录 教程大纲  硬件需求 教程说明 教程章节链接 ESP32搭建WEB服务器一(AP配网) ESP32搭建WEB服务器二(STA模式) ESP32搭建WEB服务器三(AP模式与STA模式共存) ESP32搭建WEB服务器四(最简单的WEB服务器) ESP32搭建WEB服务器五(内嵌HTML) ESP32搭建WEB服务器六(利用SPIFFS存放html,css,js等文件(读取

    2024年02月13日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包