物联网中的ESP8266该这么用!

news2024/9/21 1:29:00

🙌秋名山码民的主页
😂oi退役选手,Java、大数据、单片机、IoT均有所涉猎,热爱技术,技术无罪
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
获取源码,添加WX

目录

  • 1. 前言
  • 2. 概述esp8266
  • 3. AT命令来控制模块
  • 4. MQTT协议的概述
  • 5. 示例
  • 最后


1. 前言

在学习物联网的过程中,大家首先想到的通信应该就是蓝牙和wifi了,而wifi中又属esp8266比较出名,包括esp32的快速崛起也离不开起本身内置wife和蓝牙,这个模块本身可以连接路由器,也可以作为热点让你的手机来连接他。
本文主要从以下几个方面来进行讲解:

  1. 简单概述esp8266
  2. 搞定其AT指令集
  3. MQTT协议的概述
  4. 示例

2. 概述esp8266

ESP8266是一款以太网控制器芯片,由乐鑫科技(Espressif Systems)推出。它是一种低成本、高性能的Wi-Fi模块,广泛应用于物联网和嵌入式系统领域。
在这里插入图片描述

  1. 完整的WIFE网络解决方案,可独立运行,也可作为模块从动装置搭载到其他soc
  2. ESP8266模块内部集成了Wi-Fi无线通信功能,支持802.11b/g/n标准,可以连接到无线网络并进行数据传输。它通过串口与主控设备通信,并提供了AT指令集,简化了与主控设备的交互
  3. 可以采用Arduino IDE、MicroPython、NodeMCU等多种开发环境
  4. ESP8266具有良好的可扩展性,可以通过外部Flash存储器扩展其储存容量,支持OTA(Over-The-Air)固件升级
  5. ESP8266 RTOS SDK,支持FreeRTOS操作系统

具体参数:
在这里插入图片描述
在这里插入图片描述

硬件接口介绍:
在这里插入图片描述

  • UART接口:UART(通用异步收发传输器)接口是ESP8266与其他设备进行串行通信的主要接口,它可通过RX和TX引脚连接到其他设备。通过UART接口,可以实现与计算机、传感器、其他微控制器等设备的数据收发和控制。

  • GPIO口:ESP8266具有多个GPIO(通用输入/输出)口,用于与其他外围设备进行交互。GPIO口支持数字输入输出和PWM功能,可以通过编程来控制各种外设,如LED灯、继电器、开关等。

  • I2C接口:I2C(Inter-Integrated Circuit)接口是一种串行通信接口,可以连接多个设备,使用两根线(SDA和SCL)实现数据传输。ESP8266通过I2C接口可以与其他I2C设备通信,如传感器、显示屏等。

  • SPI接口:SPI(Serial Peripheral Interface)接口也是一种串行通信接口,可以连接多个设备,使用四根线(MISO、MOSI、SCK和SS)实现数据传输。ESP8266通过SPI接口可以与其他SPI设备通信,如Flash存储器、LCD显示屏等。

  • ADC接口:ESP8266内部集成了一个ADC(模数转换器),用于将模拟信号转换为数字信号。ADC接口可以连接到传感器等模拟设备,读取模拟值并将其转换为数字数据。

  • PWM接口:ESP8266的GPIO口支持PWM(脉冲宽度调制)功能,可用于控制电机、灯光等外设的亮度和速度。

  • SDIO接口:SDIO(Secure Digital Input Output)接口是一种高速的串行数据接口,常用于SD卡和MMC卡的读写操作。ESP8266通过SDIO接口可以连接到SD卡或MMC卡,实现数据存储和读取。

3. AT命令来控制模块

esp8266按照乐鑫官方的指令有上百条,但是常用的就10来条,下面我列举一些,其他的读者若需要可以下载乐鑫的用户手册查看。

  1. AT:测试ESP8266模块是否在线,并返回“OK”表示模块正常工作。
  2. AT+RST:重置ESP8266模块,并返回“ready”表示模块已经准备好。
  3. AT+CWMODE=:设置ESP8266的工作模式,其中参数取值为1、2或3,分别对应STA模式、AP模式和STA+AP模式。
  4. AT+CWJAP=,:连接到指定的Wi-Fi网络,其中和分别为需要连接的Wi-Fi网络名称和密码。该指令执行成功后,ESP8266会自动获取IP地址。
  5. AT+CIFSR:获取ESP8266当前IP地址。
  6. AT+CIPMUX=:设置ESP8266的多连接模式,其中参数取值为0或1,分别表示单连接模式和多连接模式。
  7. AT+CIPSTART=,,:建立TCP或UDP连接,其中参数为“TCP”或“UDP”,参数为连接目标IP地址,参数为连接目标端口号。
  8. AT+CIPSEND=:设置ESP8266发送数据的长度,其中参数为待发送数据的长度,发送数据时需先执行该指令。
  9. AT+CIPCLOSE:关闭ESP8266当前连接。

记得把端口打开:Windows打开特定端口

使用的调试助手为野火多功能调试助手
在这里插入图片描述

AT参考

4. MQTT协议的概述

MQTT(Message Queuing Telemetry Transport)是一种轻量级的、基于发布/订阅模型的消息传输协议,适用于物联网和移动应用等场景,他们之间的关系大概就像下面这张图一样:
在这里插入图片描述
具体协议介绍,后续有机会,单独开一篇来讲解。

5. 示例

代码取自野火,完整代码在野火论坛,公开资料

通用代码:

  1. 初始化函数
void ESP8266_Init ( void )
{
	ESP8266_GPIO_Config (); 
	
	ESP8266_USART_Config (); 
	
	
	macESP8266_RST_HIGH_LEVEL();

	macESP8266_CH_ENABLE();
	
	
}
  1. 初始化GPIO
static void ESP8266_GPIO_Config ( void )
{
	/*定义一个GPIO_InitTypeDef类型的结构体*/
	GPIO_InitTypeDef GPIO_InitStructure;


	/* 配置 CH_PD 引脚*/
	macESP8266_CH_PD_APBxClock_FUN ( macESP8266_CH_PD_CLK, ENABLE ); 
											   
	GPIO_InitStructure.GPIO_Pin = macESP8266_CH_PD_PIN;	

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
   
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

	GPIO_Init ( macESP8266_CH_PD_PORT, & GPIO_InitStructure );	 

	
	/* 配置 RST 引脚*/
	macESP8266_RST_APBxClock_FUN ( macESP8266_RST_CLK, ENABLE ); 
											   
	GPIO_InitStructure.GPIO_Pin = macESP8266_RST_PIN;	

	GPIO_Init ( macESP8266_RST_PORT, & GPIO_InitStructure );	 


}
  1. 初始化串口
static void ESP8266_USART_Config ( void )
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	
	/* config USART clock */
	macESP8266_USART_APBxClock_FUN ( macESP8266_USART_CLK, ENABLE );
	macESP8266_USART_GPIO_APBxClock_FUN ( macESP8266_USART_GPIO_CLK, ENABLE );
	
	/* USART GPIO config */
	/* Configure USART Tx as alternate function push-pull */
	GPIO_InitStructure.GPIO_Pin =  macESP8266_USART_TX_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(macESP8266_USART_TX_PORT, &GPIO_InitStructure);  
  
	/* Configure USART Rx as input floating */
	GPIO_InitStructure.GPIO_Pin = macESP8266_USART_RX_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(macESP8266_USART_RX_PORT, &GPIO_InitStructure);
	
	/* USART1 mode config */
	USART_InitStructure.USART_BaudRate = macESP8266_USART_BAUD_RATE;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(macESP8266_USARTx, &USART_InitStructure);
	
	
	/* 中断配置 */
	USART_ITConfig ( macESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中断 
	USART_ITConfig ( macESP8266_USARTx, USART_IT_IDLE, ENABLE ); //使能串口总线空闲中断 	

	ESP8266_USART_NVIC_Configuration ();
	
	
	USART_Cmd(macESP8266_USARTx, ENABLE);
	
	
}
  1. 配置中断
static void ESP8266_USART_NVIC_Configuration ( void )
{
	NVIC_InitTypeDef NVIC_InitStructure; 
	
	
	/* Configure the NVIC Preemption Priority Bits */  
	NVIC_PriorityGroupConfig ( macNVIC_PriorityGroup_x );

	/* Enable the USART2 Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = macESP8266_USART_IRQ;	 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

}

常规的结束,接下来就是移植代码,ESP8266,接收发送模块化代码


/*
 * 函数名:ESP8266_Rst
 * 描述  :重启WF-ESP8266模块
 * 输入  :无
 * 返回  : 无
 * 调用  :被 ESP8266_AT_Test 调用
 */
void ESP8266_Rst ( void )
{
	#if 0
	 ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 );   	
	
	#else
	 macESP8266_RST_LOW_LEVEL();
	 Delay_ms ( 500 ); 
	 macESP8266_RST_HIGH_LEVEL();
	#endif

}


/*
 * 函数名:ESP8266_Cmd
 * 描述  :对WF-ESP8266模块发送AT指令
 * 输入  :cmd,待发送的指令
 *         reply1,reply2,期待的响应,为NULL表不需响应,两者为或逻辑关系
 *         waittime,等待响应的时间
 * 返回  : 1,指令发送成功
 *         0,指令发送失败
 * 调用  :被外部调用
 */
bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime )
{    
	strEsp8266_Fram_Record .InfBit .FramLength = 0;               //从新开始接收新的数据包

	macESP8266_Usart ( "%s\r\n", cmd );

	if ( ( reply1 == 0 ) && ( reply2 == 0 ) )                      //不需要接收数据
		return true;
	
	Delay_ms ( waittime );                 //延时
	
	strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ]  = '\0';

	macPC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF );
  
	if ( ( reply1 != 0 ) && ( reply2 != 0 ) )
		return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) || 
						 ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); 
 	
	else if ( reply1 != 0 )
		return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) );
	
	else
		return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
	
}


/*
 * 函数名:ESP8266_AT_Test
 * 描述  :对WF-ESP8266模块进行AT测试启动
 * 输入  :无
 * 返回  : 无
 * 调用  :被外部调用
 */
//void ESP8266_AT_Test ( void )
//{
//	macESP8266_RST_HIGH_LEVEL();
//	
//	Delay_ms ( 1000 ); 
//	
//	while ( ! ESP8266_Cmd ( "AT", "OK", NULL, 500 ) ) ESP8266_Rst ();  	

//}
void ESP8266_AT_Test ( void )
{
	char count=0;
	
	macESP8266_RST_HIGH_LEVEL();	
	Delay_ms ( 1000 );
	while ( count < 10 )
	{
		if( ESP8266_Cmd ( "AT", "OK", NULL, 500 ) ) return;
		ESP8266_Rst();
		++ count;
	}
}


/*
 * 函数名:ESP8266_Net_Mode_Choose
 * 描述  :选择WF-ESP8266模块的工作模式
 * 输入  :enumMode,工作模式
 * 返回  : 1,选择成功
 *         0,选择失败
 * 调用  :被外部调用
 */
bool ESP8266_Net_Mode_Choose ( ENUM_Net_ModeTypeDef enumMode )
{
	switch ( enumMode )
	{
		case STA:
			return ESP8266_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 ); 
		
	  case AP:
		  return ESP8266_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 ); 
		
		case STA_AP:
		  return ESP8266_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 ); 
		
	  default:
		  return false;
  }
	
}


/*
 * 函数名:ESP8266_JoinAP
 * 描述  :WF-ESP8266模块连接外部WiFi
 * 输入  :pSSID,WiFi名称字符串
 *       :pPassWord,WiFi密码字符串
 * 返回  : 1,连接成功
 *         0,连接失败
 * 调用  :被外部调用
 */
bool ESP8266_JoinAP ( char * pSSID, char * pPassWord )
{
	char cCmd [120];

	sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord );
	
	return ESP8266_Cmd ( cCmd, "OK", NULL, 5000 );
	
}


/*
 * 函数名:ESP8266_BuildAP
 * 描述  :WF-ESP8266模块创建WiFi热点
 * 输入  :pSSID,WiFi名称字符串
 *       :pPassWord,WiFi密码字符串
 *       :enunPsdMode,WiFi加密方式代号字符串
 * 返回  : 1,创建成功
 *         0,创建失败
 * 调用  :被外部调用
 */
bool ESP8266_BuildAP ( char * pSSID, char * pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode )
{
	char cCmd [120];

	sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", pSSID, pPassWord, enunPsdMode );
	
	return ESP8266_Cmd ( cCmd, "OK", 0, 1000 );
	
}


/*
 * 函数名:ESP8266_Enable_MultipleId
 * 描述  :WF-ESP8266模块启动多连接
 * 输入  :enumEnUnvarnishTx,配置是否多连接
 * 返回  : 1,配置成功
 *         0,配置失败
 * 调用  :被外部调用
 */
bool ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx )
{
	char cStr [20];
	
	sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) );
	
	return ESP8266_Cmd ( cStr, "OK", 0, 500 );
	
}


/*
 * 函数名:ESP8266_Link_Server
 * 描述  :WF-ESP8266模块连接外部服务器
 * 输入  :enumE,网络协议
 *       :ip,服务器IP字符串
 *       :ComNum,服务器端口字符串
 *       :id,模块连接服务器的ID
 * 返回  : 1,连接成功
 *         0,连接失败
 * 调用  :被外部调用
 */
bool ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id)
{
	char cStr [100] = { 0 }, cCmd [120];

  switch (  enumE )
  {
		case enumTCP:
		  sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum );
		  break;
		
		case enumUDP:
		  sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum );
		  break;
		
		default:
			break;
  }

  if ( id < 5 )
    sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr);

  else
	  sprintf ( cCmd, "AT+CIPSTART=%s", cStr );

	return ESP8266_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );
	
}


/*
 * 函数名:ESP8266_StartOrShutServer
 * 描述  :WF-ESP8266模块开启或关闭服务器模式
 * 输入  :enumMode,开启/关闭
 *       :pPortNum,服务器端口号字符串
 *       :pTimeOver,服务器超时时间字符串,单位:秒
 * 返回  : 1,操作成功
 *         0,操作失败
 * 调用  :被外部调用
 */
bool ESP8266_StartOrShutServer ( FunctionalState enumMode, char * pPortNum, char * pTimeOver )
{
	char cCmd1 [120], cCmd2 [120];

	if ( enumMode )
	{
		sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum );
		
		sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver );

		return ( ESP8266_Cmd ( cCmd1, "OK", 0, 500 ) &&
						 ESP8266_Cmd ( cCmd2, "OK", 0, 500 ) );
	}
	
	else
	{
		sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum );

		return ESP8266_Cmd ( cCmd1, "OK", 0, 500 );
	}
	
}


/*
 * 函数名:ESP8266_Get_LinkStatus
 * 描述  :获取 WF-ESP8266 的连接状态,较适合单端口时使用
 * 输入  :无
 * 返回  : 2,获得ip
 *         3,建立连接
 *         3,失去连接
 *         0,获取状态失败
 * 调用  :被外部调用
 */
uint8_t ESP8266_Get_LinkStatus ( void )
{
	if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
	{
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) )
			return 2;
		
		else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) )
			return 3;
		
		else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) )
			return 4;		

	}
	
	return 0;
	
}


/*
 * 函数名:ESP8266_Get_IdLinkStatus
 * 描述  :获取 WF-ESP8266 的端口(Id)连接状态,较适合多端口时使用
 * 输入  :无
 * 返回  : 端口(Id)的连接状态,低5位为有效位,分别对应Id5~0,某位若置1表该Id建立了连接,若被清0表该Id未建立连接
 * 调用  :被外部调用
 */
uint8_t ESP8266_Get_IdLinkStatus ( void )
{
	uint8_t ucIdLinkStatus = 0x00;
	
	
	if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
	{
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:0," ) )
			ucIdLinkStatus |= 0x01;
		else 
			ucIdLinkStatus &= ~ 0x01;
		
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:1," ) )
			ucIdLinkStatus |= 0x02;
		else 
			ucIdLinkStatus &= ~ 0x02;
		
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:2," ) )
			ucIdLinkStatus |= 0x04;
		else 
			ucIdLinkStatus &= ~ 0x04;
		
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:3," ) )
			ucIdLinkStatus |= 0x08;
		else 
			ucIdLinkStatus &= ~ 0x08;
		
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:4," ) )
			ucIdLinkStatus |= 0x10;
		else 
			ucIdLinkStatus &= ~ 0x10;	

	}
	
	return ucIdLinkStatus;
	
}


/*
 * 函数名:ESP8266_Inquire_ApIp
 * 描述  :获取 F-ESP8266 的 AP IP
 * 输入  :pApIp,存放 AP IP 的数组的首地址
 *         ucArrayLength,存放 AP IP 的数组的长度
 * 返回  : 0,获取失败
 *         1,获取成功
 * 调用  :被外部调用
 */
uint8_t ESP8266_Inquire_ApIp ( char * pApIp, uint8_t ucArrayLength )
{
	char uc;
	
	char * pCh;
	
	
  ESP8266_Cmd ( "AT+CIFSR", "OK", 0, 500 );
	
	pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "APIP,\"" );
	
	if ( pCh )
		pCh += 6;
	
	else
		return 0;
	
	for ( uc = 0; uc < ucArrayLength; uc ++ )
	{
		pApIp [ uc ] = * ( pCh + uc);
		
		if ( pApIp [ uc ] == '\"' )
		{
			pApIp [ uc ] = '\0';
			break;
		}
		
	}
	
	return 1;
	
}


/*
 * 函数名:ESP8266_UnvarnishSend
 * 描述  :配置WF-ESP8266模块进入透传发送
 * 输入  :无
 * 返回  : 1,配置成功
 *         0,配置失败
 * 调用  :被外部调用
 */
bool ESP8266_UnvarnishSend ( void )
{
	if ( ! ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ) )
		return false;
	
	return 
	  ESP8266_Cmd ( "AT+CIPSEND", "OK", ">", 500 );
	
}


/*
 * 函数名:ESP8266_ExitUnvarnishSend
 * 描述  :配置WF-ESP8266模块退出透传模式
 * 输入  :无
 * 返回  : 无
 * 调用  :被外部调用
 */
void ESP8266_ExitUnvarnishSend ( void )
{
	Delay_ms ( 1000 );
	
	macESP8266_Usart ( "+++" );
	
	Delay_ms ( 500 ); 
	
}


/*
 * 函数名:ESP8266_SendString
 * 描述  :WF-ESP8266模块发送字符串
 * 输入  :enumEnUnvarnishTx,声明是否已使能了透传模式
 *       :pStr,要发送的字符串
 *       :ulStrLength,要发送的字符串的字节数
 *       :ucId,哪个ID发送的字符串
 * 返回  : 1,发送成功
 *         0,发送失败
 * 调用  :被外部调用
 */
bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId )
{
	char cStr [20];
	bool bRet = false;
	
		
	if ( enumEnUnvarnishTx )
	{
		macESP8266_Usart ( "%s", pStr );
		
		bRet = true;
		
	}

	else
	{
		if ( ucId < 5 )
			sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );

		else
			sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );
		
		ESP8266_Cmd ( cStr, "> ", 0, 1000 );

		bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 1000 );
  }
	
	return bRet;

}


/*
 * 函数名:ESP8266_ReceiveString
 * 描述  :WF-ESP8266模块接收字符串
 * 输入  :enumEnUnvarnishTx,声明是否已使能了透传模式
 * 返回  : 接收到的字符串首地址
 * 调用  :被外部调用
 */
char * ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx )
{
	char * pRecStr = 0;
	
	
	strEsp8266_Fram_Record .InfBit .FramLength = 0;
	strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
	
	while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag );
	strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
	
	if ( enumEnUnvarnishTx )
		pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;
	
	else 
	{
		if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" ) )
			pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;

	}

	return pRecStr;
	
}

最后

参考资料:
《乐鑫ESP8266用户手册》
《ESP8266作为TCP服务器端使用心得》
《野火ESP8266部分例程》

如果本文对你有所帮助,还请三连支持一下博主!
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1163698.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

win10 esd文件转iso

想装个win10虚拟机&#xff0c;在系统之家下载了iso&#xff0c;然后开始装&#xff0c;发现虚拟机找不到系统&#xff0c; 插&#xff0c;啥原因&#xff0c;解压出iso一看&#xff0c;有个exe文件&#xff0c;要运行他才安装&#xff0c;不地道啊&#xff0c;现在为什么搞这…

Viessmann Vitogate远程代码执行漏洞(CVE-2023-45852)

Viessmann Vitogate远程代码执行漏洞&#xff08;CVE-2023-45852&#xff09; 免责声明漏洞描述漏洞影响漏洞危害网络测绘Fofa: body"vitogate 300" 漏洞复现1. 构造poc2. 执行命令查看用户 免责声明 仅用于技术交流,目的是向相关安全人员展示漏洞利用方式,以便更好…

SpringCloudGateway--过滤器(自定义filter)

目录 一、概览 二、通过GatewayFilter实现 三、继承AbstractGatewayFilterFactory 一、概览 当使用Spring Cloud Gateway构建API网关时&#xff0c;可以利用Spring Cloud Gateway提供的内置过滤器&#xff08;filter&#xff09;来实现对请求的处理和响应的处理。过滤器可以…

无需专线、无需固定公网IP,各地安防数据如何高效上云?

某专注于安防领域的企业&#xff0c;供机场、金融、智慧大厦等行业&#xff0c;包括门禁系统、巡更系统、视频监控在内的整体解决方案。 在实际方案交付过程中&#xff0c;往往需要在多地分支机构分别部署相应的安防设备&#xff0c;并将产生的数据实时统一汇总至云平台进行管理…

PyQuery库写一个有趣的爬虫程序

PyQuery库是一个基于jQuery语法的Python库&#xff0c;它可以方便地对HTML/XML文档进行解析和操作。使用PyQuery库可以快速地获取网页中的数据&#xff0c;进行数据清洗和分析。PyQuery库的基本用法包括字符串初始化、打开网页、css属性、标签内容等获取、DOM基本操作等相关技巧…

OSPF高级特性2(特殊区域,聚合)

目录 一、特殊区域 1、STUB区域&#xff1a; 2、totally stub区域 3、NSSA区域&#xff08;Not-So-stubby Area&#xff09; 4、totally NSSA区域 二、OSPF路由聚合 一、特殊区域 定义&#xff1a;特殊区域是指人为定义的一些区域&#xff0c;它们在逻辑中一般位于ospf区…

shell script 案例二

需求&#xff0c;运行程序&#xff0c;用户输入firstname&#xff0c;回车&#xff0c;再次提示输入lastname&#xff0c;然后回车&#xff0c;屏幕打印fullname信息 注意&#xff1a;前期写程序要注意规范&#xff0c;方便以后自己写多了回头看可以看的懂&#xff0c;程序代码…

2023年【低压电工】考试及低压电工模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 低压电工考试根据新低压电工考试大纲要求&#xff0c;安全生产模拟考试一点通将低压电工模拟考试试题进行汇编&#xff0c;组成一套低压电工全真模拟考试试题&#xff0c;学员可通过低压电工模拟考试题全真模拟&#…

josef约瑟 DJS-1/G 跳闸回路监视继电器 AC220V

系列型号 DJS-1跳闸回路监视继电器 DJS-1G跳闸回路监视继电器 DJS-1/G跳闸回路监视继电器 一、用途 DJS-1型跳闸回路监视继电器可连续监视短路器中的跳闸回路。并对下列情况产生报警。 a&#xff09;DC电源消失&#xff1b; b&#xff09;跳闸线圈及其引线发生故障&#…

Intel oneAPI笔记(1)--oneAPI简介、SYCL编程简介

oneAPI简介 Intel oneAPI是Intel提供的统一编程模型和软件开发框架。 它旨在简化可充分利用英特尔各种硬件架构&#xff08;包括 CPU、GPU 和 FPGA&#xff09;的应用程序的开发 oneAPI一个重要的特性是开放性&#xff0c;支持多种类型的架构和不同的硬件供应商&#xff0c;是…

何恺明:在cuhk解答科研问题

文章目录 1. 大模型的未来:数据效益是个问题2. 未来三年研究重点:视觉自监督学习3. 选择课题的标准:好奇心和热情4. AI将成为几乎所有事情的基础工具5. 用疑问解答AI模型可解释性问题AcknowledgementReference何恺明最近在香港中文大学参加一个讲座过程中所述: 1. 大模型的…

MT8365安卓核心板—联发科MTK8365(I350)性能参数

MT8365安卓核心板是基于联发科MTK8365芯片开发的一款高性能核心板。该核心板模块板载内存容量为1GB8GB(也可选择2GB16GB、3GB32GB、4GB64GB)&#xff0c;默认搭载谷歌的Android 11.0系统。它集成了丰富的功能接口&#xff0c;包括LCM接口、摄像头接口、触摸屏接口、麦克风接口、…

[计算机提升] Windows系统软件:娱乐类

3.3 系统软件&#xff1a;娱乐类 3.3.1 Windows Media Player&#xff1a;dvdplay Windows Media Player是Windows操作系统自带的多媒体播放软件&#xff0c;用于播放和管理电脑中的音频和视频文件。它提供了以下功能&#xff1a; 播放音频和视频文件&#xff1a;Windows Med…

hugetlb核心组件

1 概述 hugetlb机制是一种使用大页的方法&#xff0c;与THP(transparent huge page)是两种完全不同的机制&#xff0c;它需要&#xff1a; 管理员通过系统接口reserve一定量的大页&#xff0c;用户通过hugetlbfs申请使用大页&#xff0c; 核心组件如下图&#xff1a; 围绕着…

农业中的机器学习

机器学习训练模型推荐&#xff1a; UnrealSynth虚幻合成数据生成器 - NSDT 机器学习是一个不断发展的领域&#xff0c;在农业中有许多潜在的应用。农民和农业科学家正在探索如何转向机器学习开发来提高作物产量、减少用水量和预测病虫害。未来&#xff0c;机器学习可以帮助农民…

内存管理设计精要

系统设计精要是一系列深入研究系统设计方法的系列文章&#xff0c;文中不仅会分析系统设计的理论&#xff0c;还会分析多个实际场景下的具体实现。这是一个季更或者半年更的系列&#xff0c;如果你有想要了解的问题&#xff0c;可以在文章下面留言。 持久存储的磁盘在今天已经不…

多特征线性回归模型

一、预测目标和原始数据展示 (一)预测目标: 通过Economy..GDP.per.Capita.(GDP)和Freedom预测Happiness.Score (二)部分数据展示: 特征有很多&#xff0c;本文研究Economy..GDP.per.Capita.(GDP)和Freedom&#xff0c;也就是用Economy..GDP.per.Capita.(GDP)和Freedom预测Happ…

B端企业形象设计的正确姿势,你学会了吗?

如今&#xff0c;企业形象设计在B端市场中变得越来越重要。它是企业与客户之间建立联系的桥梁&#xff0c;也是吸引目标客户的重要方式。为了帮助您打造一个独特而专业的企业形象设计&#xff0c;我将为您提供十个步骤。 步骤1&#xff1a;了解企业定位和目标 在设计B端企业形…

Angular模板语法

1 Angular数据文本绑定 Angular 中使用{{}}绑定业务逻辑里面定义的数据 <div class"title"> {{title}}</div>2 Angular模板里面绑定属性 [title]"student"绑定动态属性 ts: public title: string zhaoshuai-lc html: <div [title]"…

自制目录扫描工具并由py文件转为exe可执行程序

心血来潮让ChatGPT写了一个目录扫描工具&#xff0c;然后进行了一定的修改和完善&#xff0c;可以实现对网站目录的一个简单扫描并输出扫描结果&#xff0c;主要包括存在页面、重定向页面和禁止访问页面。 虽然代码很简单&#xff0c;但是做这个东西的过程还是挺有意思的&…