STM32从ESP获取时间(AT)

串口初始化代码就不分享了,大家都有的,我做的是回环测试,也就是用了两个串口,一个串口给ESP8266发送指令,另一个接收他发回来的数据,如果需要代码最后会给
先分享一下代码,大概讲解一下(从简)

建立连接

//Server:服务器类型	IP:服务器地址	PORT:端口号
void ESP_CIPSTART(const char* Server,const char* IP,const char* PORT)
{
	char temp[40] = {0};
	uint8_t k = 0;
	sprintf(temp,"AT+CIPSTART=\"%s\",\"%s\",%s\r\n",Server,IP,PORT);
	while(temp[k]!='\0')
	{
		USART_SendByte(ESP_USARTx,temp[k]);
		while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TXE) == RESET);
		k++;
	}
	while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TC) ==RESET);
}

CIPSTART不懂,那就去先了解AT指令,附上别人的分享
https://blog.csdn.net/lalala098/article/details/81240806

检测响应

//rsp:你要检测的响应字符串,waitTimes_ms:超时退出
uint8_t ESP_Check_Respond(const char* rsp,u16 waitTimes_ms)
{
	while((strstr(ESP_Usart_RecBuf,rsp) == NULL)&&(--waitTimes_ms))
	{
		delay_ms(1);
	}
	if(waitTimes_ms) return SUCCESS;
	else return ERROR;
}

strstr是标准库string.h的,include

发送命令字符串

//Enter是否加入换行 1就加入
void ESP8266_SendATcmd(const char* AT_cmd,u8 Enter)
{
	char CMDBuf[20] = {0};
	uint8_t k = 0;
	strcat(CMDBuf,AT_cmd);
	if(Enter)
	{	
		strcat(CMDBuf,"\r\n");	//加入换行
	}
	while(*(CMDBuf+k)!='\0')
	{
		USART_SendByte(ESP_USARTx,*(CMDBuf+k));
		while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TXE) == RESET);
		k++;
	}
	while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TC) ==RESET);
}
void ESP_SendString(const char* str)
{
	uint8_t k = 0;
	do
	{
		USART_SendByte(ESP_USARTx,str[k]);
		while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TXE) == RESET);
		k++;
	}while(*(str+k)!='\0');
	while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TC) == RESET);
}

发送AT指令、发送字符串(向ESP8266)
基于上面两个函数,我定义了一些宏

#define	OPEN_PTMODE()				ESP8266_SendATcmd("AT+CIPMODE=1",1)	//打开透传模式,要记得关
#define	CLOSE_PTMODE()				ESP_SendString("+++")				//退出透传模式(重要!不然会一直接收数据)
#define	CMD_CIPCLOSE()				ESP_SendString("AT+CIPCLOSE\r\n")	//退出IP
#define CMD_AT()					ESP8266_SendATcmd(AT,CMD_ENTER)
#define	CMD_RST()					ESP8266_SendATcmd(AT_RST,CMD_ENTER)

获取时间

NETWORK_TIME myTime;
//获取网络时间
uint8_t Get_NetWork_Time(void)
{
	
	uint8_t GetFlag = 0;
	ESP_CIPSTART("TCP","www.beijing-time.org","80");
	delay_ms(50);
	if(ESP_Check_Respond("CONNECT",400) == 0)
	{
		ESP_ERROR("ERROR0");
		return 0;
	}
	//delay_ms(1000);
	OPEN_PTMODE();							//开透传
	delay_ms(50);
	if(ESP_Check_Respond("OK",400) == 0)
	{
		CLOSE_PTMODE();	
		ESP_ERROR("ERROR1");
		return 0;
	}
	ESP8266_SendATcmd("AT+CIPSEND",1);
	delay_ms(50);
	if(ESP_Check_Respond("OK",400) == 0)
	{
		CLOSE_PTMODE();	
		ESP_ERROR("ERROR1");
		return 0;
	}
	ESP_SendString("GET /time15.asp HTTP/1.1\r\nHost:www.beijing-time.org\r\n");
	ESP_SendString("GET /time15.asp HTTP/1.1\r\nHost:www.beijing-time.org\r\n");
	delay_ms(500);
	if(GetNET_Time(&myTime,ESP_Usart_RecBuf))	GetFlag = 1;
	//delay_ms(1000);
	CLOSE_PTMODE();		//关透传
	delay_ms(50);	
	CMD_CIPCLOSE();		//退出IP
	delay_ms(50);					
	return GetFlag;
}

先别急着看代码,我说一下这个函数的流程是,建立连接,开启透传(记得关).发送CIPSEND指令开始进入发送模式,然后发送两次获取时间的字符串(不知道为什么要发两次),然后通过一个函数(GetNET_Time)提取时间数据,成功提取返回1,失败为0,最后关闭透传,切记),退出连接.下面分享一下怎么提取数据。

提取时间数据

先给大家看一下格式

HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Thu, 30 Jul 2020 13:58:01 GMT
Connection: close
Content-Length: 339

很明显,Date后面就是数据了,这样照葫芦画瓢,定义一个结构体来存储这些数据

typedef struct
{
	char week[5];
	char date[3];
	char month[5];
	char year[6];
	char hours[4];
	char minute[4];
	char seconds[4];
} NETWORK_TIME;

上代码

uint8_t GetNET_Time(NETWORK_TIME* time,char *Timestr)
{
	char* pbuf = NULL;
	pbuf = strstr(Timestr,"Date:");
	if(pbuf)
	{
		if(sscanf(pbuf,"%*[^:]: %[^,], %[^ ] %[^ ] %[^ ] %[^:]:%[^:]:%[^ ]",
		time->week,time->date,time->month,time->year,time->hours,time->minute,time->seconds))
		{
			return 1;
		}
	}
	return 0;
}

sscanf在stdio.h, include进去,sscanf用法自己查
说一下过程,传入数组缓冲区数据,然后用strstr函数查找”Date:“这个字符所在位置(指针),最后传入sscanf按格式提取出年月日。。。等时间数据(字符串)。
可能有些人不懂数组缓冲区,我以前发了一篇IDLE中断,需要的可以看看,同样可以定义一个ESP用到的串口的接收缓冲。
下面来测试一下结果,分享我的测试代码


extern NETWORK_TIME myTime;
int thour;
int tmin;
int tsec;
int main()
{
	/*Parameter Configuration*/
	
	/*Init*/
	delay_init(168);
	USART_Config();
	LED_GPIO_Config();
	ESP8266_USART_Config();	//初始化ESP的串口
	ESP_Idle_Receive_Config();	//初始化空闲接收中断
	/*Configuration Operation*/
	ESP8266_SendATcmd("AT+RST",1);	//一定要复位一下,并且连上WIFI,CWMODE=1或者3
	if(Get_NetWork_Time())
		{
			sscanf(myTime.hours,"%d",&thour);
			sscanf(myTime.minute,"%d",&tmin);
			sscanf(myTime.seconds,"%d",&tsec);
			printf("\r\n%s %d:%d:%d",myTime.year,thour+8,tmin,tsec);
		}
	/*LOOP*/
	while(1)
	{
		LED1_TOGGLE;
		delay_ms(500);
	}
}

我把字符串转化成整型了,其实也可以直接使用字符串,%s就行了,我转成整型是因为时间有时差,那是0度线的时间,我也不知道哪里,北京时间+8就对了(东8区?)
我的结果:
在这里插入图片描述

回环测试

#define	ESP_USE_IDLE_RECEIVE		//是否开启空闲接收中断
#define ESP_USART_REC_BUFSIZE		100
//头文件↑

static u16 ESP_Usart_Count = 0;		//接收计数,在中断函数调用
char ESP_Usart_RecBuf[ESP_USART_REC_BUFSIZE]; 
#ifdef ESP_USE_IDLE_RECEIVE
void ESP_USARTx_IRQHandle()
{
	u16 times;
	if(USART_GetITStatus(ESP_USARTx,USART_IT_RXNE) != RESET)
	{
		ESP_Usart_RecBuf[ESP_Usart_Count] = USART_ReceiveData(ESP_USARTx);
		ESP_Usart_Count++;
	}
	if(USART_GetITStatus(ESP_USARTx,USART_IT_IDLE) != RESET)
	{
		ESP_Usart_RecBuf[ESP_Usart_Count] = USART_ReceiveData(ESP_USARTx);
		//ESP_Usart_Count++;
		/*此处加入对接收缓冲区的操作*/
		for(times = 0;times < ESP_Usart_Count;times++)
		{
			USART_SendByte(DEBUG_USART,ESP_Usart_RecBuf[times]);
		}
		ESP_Usart_Count = 0;
	}
}
#endif

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 要在STM32和ESP8266上获取网络时间,可以使用以下步骤: 1. 首先,需要将ESP8266连接到WiFi网络。可以使用AT指令或ESP8266的API来实现。 2. 一旦ESP8266连接到WiFi网络,可以使用NTP协议从互联网上获取时间。可以使用ESP8266的API或AT指令来实现。 3. 在STM32上,可以使用ESP8266的串口通信来获取时间数据。可以使用STM32的串口通信库来实现。 4. 一旦STM32获取时间数据,可以使用RTC模块来保存时间,并在需要时使用。 需要注意的是,获取网络时间需要保证ESP8266连接到互联网,并且网络稳定。同时,需要确保STM32和ESP8266之间的串口通信正常。 ### 回答2: STM32和ESP8266均是常见的物联网开发板,通过将它们结合起来,可以实现许多有用的功能。其中之一就是获取网络时间,从而确保设备的时间同步。 具体实现方法如下: 1. 搭建硬件平台:先将STM32与ESP8266通过串口连接,确保二者可以相互通信。接着在STM32上搭建定时器,控制每隔一定时间ESP8266发送网络时间请求指令。 2. 配置ESP8266:开发者需要利用ESP8266手册或官方API文档,了解ESP8266相关AT指令,用于和服务器通信,请求网络时间信息,有时也可通过SNTP服务器获取时间信息。 3. 接收指令:ESP8266接收到STM32发送的命令后,向服务器发送请求信号,然后等待响应。这可以通过向服务器发送网络探测数据包实现。 4. 返回结果:服务器响应ESP8266的请求,将时间数据发送到ESP8266上。ESP8266接收到服务器返回的数据后,通过串口将数据发送给STM32,由STM32进行处理。 5. 时间同步:STM32获取到网络时间数据后,通过RTC实时时钟进行同步,从而确保设备时间与网络时间保持同步,同时在必要时可存入EEPROM,以便下次开机时不必重新获取网络时间。这个步骤实现硬件RTC时间校准。 实际实现过程中,还需要考虑网络延迟、数据传输稳定性、数据格式处理等细节问题,从而保证功能的可靠性和稳定性。此外,在应用中还可根据具体需求,设计更加高级和实用的时间同步方案。 ### 回答3: stm32esp8266是一款嵌入式系统,通过WiFi模块可以连接互联网。获取网络时间是嵌入式系统中一个非常关键的功能,在许多应用中都需要使用到时间,比如时钟、定时器、计时等等。 首先需要连接WiFi模块,获取网络连接。这可以通过AT指令或者通过HTTP协议实现。常见的AT指令有AT+CWMODE,用来设置WiFi模式,AT+CWJAP用来加入WiFi网络。当连接到网络后,可以使用NTP协议获取网络时间。 NTP协议是一种时间同步协议,它可以通过网络协议将计算机时钟同步到一个准确定时。NTP协议的服务器可以通过GPS信号或者基于原子钟的时间源来提高时间同步的准确性。在获取网络时间之前,需要通过DNS服务解析NTP服务器的IP地址。 在stm32esp8266中,可以使用sockets套接字建立网络连接,并向NTP服务器发送指令以获取网络时间。比如使用setsockopt函数设置socket连接选项,使用connect函数连接服务器,使用send和recv函数发送和接收数据。 获取到网络时间后,需要处理时间格式,使其符合系统的时间格式。通常的做法是将网络时间转换为UTC毫秒时间戳,然后再转换为其他格式。可以通过第三方库或者自行实现来完成时间格式转换。 最后,将获取时间存储在系统的时间寄存器中,以便在使用时能够直接读取。在stm32esp8266中,可以利用RTC实现时间存储和时间解析功能。 综上,获取网络时间在嵌入式系统中非常重要,在stm32esp8266中也需要通过多方面的技术手段来实现。需要注意的是,在网络不稳定的情况下,可能会造成获取时间不准确。因此,在应用中需要考虑到这种情况,并进行相应的处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值