esp12实现的网络时钟校准

网络时间的获取是通过向第三方服务器发送GET请求获取并解析出来的。

在本篇博客中,网络时间的获取是一种自动的行为,当系统成功连接WiFi获取到网络天气后,系统将自动获取并解析得到时间和日期,为了减少误差每两分钟左右进行一次校准。在网络时间成功获取后,定时器中时间计数从这个数开始,并且到达一定数目,系统自动更新上下午和日期信息。

时间日期显示设计如图所示:

访问网络服务器校准网络时钟,需要了解服务器返回给我们的json字符串格式。可以用CJSON库进行解析,但是这里我采用手动解析。

            {
            "success": "1",
            "result": {
            "timestamp": "1718090343",
            "datetime_1": "2024-06-11 15:19:03",
            "datetime_2": "2024年06月11日 15时19分03秒",
            "week_1": "2",
            "week_2": "星期二",
            "week_3": "周二",
            "week_4": "Tuesday"
                }
            }

对应的接收代码

if(comGetChar(COM3,&getChar))
{	
		switch(state)
		{
			case 0:
				if(getChar == '{'){ state=1;}
						Recv_len=0;
						break;
					case 1:
						if(getChar == '}') 
						{
							state=0;
							Recv_CommandFlag=TIMERECV;
						}
						else
						{
							*(Recv_Buf+Recv_len) = getChar;
							Recv_len++;
							printf("%c",getChar);
							if(Recv_len>=210)
							{
								Recv_CommandFlag=UNRECV;
								state=0;
							}
						}
						break;
					default:
						break;
				}
			}

 解析调用

Recv_CommandFlag = 0;
		ret = timeParse(Recv_Buf);
		if(ret == 0)
		{
			Times_Change(myday,mymonth,myyear);    //计算当前日期
			Display_days(myyear, mymonth, myday);  //显示日期
			GetTimes(myhour,myminute,mysecond);Display_time(TIMES);
		}else{
			printf("\r\ntimeParse fail\r\n");
		}
		NetStatus=ESP_TLINK_INIT;//回去弄tlink看看是不是有网

mytime.c

#include "mytime.h"
#include "esp8266.h"

volatile uint32_t TIMES = 0;

void GetTimes(char h,char m, char s )
{
	TIMES=h*60*60+m*60+s;
	return;
}
void Times_Change(unsigned char d, unsigned char m, int y)
{
	if(m == 2)    //如果是2月
	{
		 if(d == 29)
		 {
			 if(!((((y%4) == 0) && ((y%100) != 0)) || ((y % 400) == 0)))  //如果不是闰年
			 {
				m ++;    
				d = 1;
			 }
		 }
		 else if(d == 30)
		 {
			 if((((y%4) == 0) && ((y%100) != 0)) || ((y % 400) == 0))  //如果是闰年
		   {
				m ++;    
				d = 1;
		   }
		 }	 
	}
	 else if(d == 31)
	 {
		  if(m == 4 | m == 6 | m == 9 | m == 11)
		  { 
			  m ++; 
			  d = 1;
		  }
	 }
	 else if(d > 31)
	 {							 
		if(m == 12)
		{
		  y ++;
		  m = 1;
		  d = 1;
		}								 
		else
		{
			m ++; 
			d = 1;
		}
	 }
}


/*-------------------------------------------------------------
 *计算时间函数  
 *起始页地址  宏定义  TIME_START_PAGE
 *起始列地址  宏定义  TIME_START_COL
 *时间  times   为0~86399,即24小时最大秒数
 *分别计算出时 分 秒 上 下午 并显示在相应位置
 *-------------------------------------------------------------*/
void Display_time(unsigned int times)    
{
	char timeStr_lvgldisp[30];
	unsigned int temp_time = times;
	unsigned char temp_hour, temp_minutues, temp_seconds;
	unsigned char t_h_ten, t_h_one, t_m_ten, t_m_one, t_s_ten, t_s_one;
	char timewhen;
	
	temp_hour = times / 3600;            //得到小时数
	temp_minutues =(times % 3600) / 60;  //得到分钟数
	temp_seconds = (times % 3600) % 60;  //得到秒数
	
	myhour=temp_hour;
	myminute=temp_minutues;
	mysecond=temp_seconds;
	
	t_h_ten = temp_hour / 10;          //取小时十位数
	t_h_one = temp_hour % 10;          //取小时个位数
	t_m_ten = temp_minutues /10;       //取分钟十位数
	t_m_one = temp_minutues %10;       //取分钟个位数
	t_s_ten = temp_seconds /10;        //取秒十位数
	t_s_one = temp_seconds %10;        //取秒个位数
	
	
	if(temp_time < 43200)    //上午
	{
		timewhen='A';
	}
	else  //下午
	{
		timewhen='P';
	}
	sprintf((char *)timeStr_lvgldisp, "%d%d:%d%d:%d%d-%cM",t_h_ten,t_h_one,t_m_ten,t_m_one,t_s_ten,t_s_one,timewhen);
	printf("\r\ntimeStr:%s\n\r",(char *)timeStr_lvgldisp);
}

/*-------------------------------------------------------------
 *计算日期和星期函数
 *日期起始页地址  宏定义  DAYS_START_PAGE
 *日期起始列地址  宏定义  DAYS_START_COL
 *星期起始页地址  宏定义  WEEK_START_PAGE
 *星期起始列地址  宏定义  WEEK_START_COL
 *日期  days   为0~86399,即24小时最大秒数
 *计算出星期 和日期 并显示在相应位置
 *
 * 吉姆拉尔森公式:w=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)mod7
 *w:week, y = year , m = moon, d = day , 1月=13月,2月=14月
 *w = 0,星期一 ~ w = 6,星期日 
 *-------------------------------------------------------------*/
void Display_days(int year, unsigned char moon, unsigned char day)
{
	char dateStr[20];
	int temp_year, temp_moon, temp_day, temp_week;
	unsigned char t_y_frist, t_y_second, t_y_thrid, t_y_forth;
	unsigned char t_m_ten, t_m_one, t_d_ten, t_d_one;
	int y, m, d;

	temp_year = year;
	temp_moon = moon; 
	temp_day = day;
	  
	t_y_frist = temp_year / 1000;
	t_y_second = (temp_year % 1000) / 100;
	t_y_thrid = (temp_year % 100) / 10;
	t_y_forth = temp_year % 10;

	t_m_ten = temp_moon / 10;
	t_m_one = temp_moon % 10;
	t_d_ten = temp_day / 10;
	t_d_one = temp_day % 10;

	y = year;
	m = moon;
	d = day;

	if((m == 1) || (m == 2))
	{
		m += 12;
		y --;
	}
	temp_week = ((d +2*m + 3*(m + 1) / 5 + y +y/4 - y /100 +y/400)%7)+1;   //计算星期几 
	myweek = temp_week;  //汉字一为第1个字符,方便计算
	
	sprintf((char *)dateStr, "%d%d%d%d-%d%d-%d%d:%d",t_y_frist,t_y_second,t_y_thrid,t_y_forth,t_m_ten,t_m_one,t_d_ten,t_d_one,temp_week);
	printf("dateStr:%s\n\r",(char *)dateStr);
}





mytime.h

#ifndef __MYTIME__
#define __MYTIME__

#include "stdint.h"

extern volatile uint32_t TIMES;

//extern char timeStr_lvgldisp[30];

void Times_Change(unsigned char d, unsigned char m, int y);
void Display_time(unsigned int times);
void Display_days(int year, unsigned char moon, unsigned char day);
void GetTimes(char h,char m, char s );

#endif

发起请求

ESP_Fefresh_NET_Massage(wifi_ssid,wifi_password,time_address,time_point,GetNet_Time);	

key str的链接,删掉“GET”后复制粘贴浏览器应该是可以看到json字符串的,看不到就说明你模块怎么访问都不会获得的,建议自己先访问看一下 

//time
char time_keystr[150]="GET http://api.k780.com:88/?app=life.time&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json&HTTP/1.1\r\n";
char time_address[25]="api.k780.com";
char time_point[5]="88";

//日期时间变量
int myyear=2024;
int mymonth=6;
int myweek=3;
int myday=12;
int myhour=21;
int myminute=31;
int mysecond=56;

char subdatetime_1[20]; 
//char subdatetime_2[8];

u8 timeParse(char * timestr)
{
	char *datetime1_start = strstr(timestr,"datetime_1"); 
	if (datetime1_start != NULL) 
	{
		datetime1_start += (strlen("datetime_1")+3); 
		strncpy(subdatetime_1, datetime1_start, 19); 
		subdatetime_1[19] = '\0'; 
		printf("datetime_1: %s\r\n", subdatetime_1);
		sscanf(subdatetime_1, "%d-%d-%d %d:%d:%d", &myyear, &mymonth, &myday, &myhour, &myminute, &mysecond);
		GetTimes(myhour,myminute,mysecond);
		return 0;
	} else {
		printf("\r\nKey not found\r\n");
		return 1;
	}
}

/*-------------------------------------------------
 * 更新网络时间函数
 * 已经连接WIFI,定期连接TCP更新网络时间
-------------------------------------------------*/

u8 ESP_Fefresh_NET_Massage(char *ssid,char *pwd,const char *tcp_addr, char *point, void (*function)())
{
	char tcp_information[160]={0};
	char wifi_information[56]={0};   //WiFi热点临时数组

	u8 return_temp = 0;
	 
	comSendBuf(COM3, (uint8_t *)"+++", 3);
	vTaskDelay(3000);
	ESP12_SendAT("AT");
	if (ESP12_WaitResponse("OK", 5000) != 1)
	{
		printf("\r\n AT fail!\r\n");
		failnum|=(1<<0);
		//vTaskDelay(1000);
	}	
	ESP12_SendAT("ATE0");
	if (ESP12_WaitResponse("OK", 5000) != 1)
	{
		printf("\r\n ATE0 fail\r\n");
		failnum|=(1<<1);vTaskDelay(1000);
	}	
	
	ESP12_SendAT("AT+CWMODE=1");
	if (ESP12_WaitResponse("OK", 5000) != 1)
	{
		printf("\r\n CWMODE fail\r\n");
		failnum|=(1<<2);vTaskDelay(2000);
	}
	
	sprintf(wifi_information, "AT+CWJAP=\"%s\",\"%s\"", ssid, pwd);  //将WiFi热点名称和密码			
	ESP12_SendAT(wifi_information);
	if (ESP12_WaitResponse("OK", 5000) != 1)
	{
		printf("\r\n CWJAP fail\r\n");
		failnum|=(1<<3);
		//vTaskDelay(1000);
	}
	
	sprintf(tcp_information, "AT+CIPSTART=\"TCP\",\"%s\",%s", tcp_addr, point);  //将TCP,地址和端口号传给临时变量
	//	printf("%s\n",tcp_information);
	ESP12_SendAT(tcp_information);
	if (ESP12_WaitResponse("OK", 5000) != 1)
	{
		printf("\r\n CIPSTART fail\r\n");
		failnum|=(1<<4);//vTaskDelay(1000);
	}
	
	ESP12_SendAT("AT+CIPMODE=1");
	if (ESP12_WaitResponse("OK", 3000) != 1)
	{
		printf("\r\n CIPMODE fail\r\n");
		failnum|=(1<<5);//vTaskDelay(1000);
	}
	
	ESP12_SendAT("AT+CIPSEND");
	if (ESP12_WaitResponse("OK", 1000) != 1)
	{
		printf("\r\n CIPMODE fail\r\n");//vTaskDelay(1000);
		failnum|=(1<<6);
	}
	// Send KeyStr
	function();
	
	return 0;
}

注意两个gettime不一样,一个是更新时间,一个是发起GET请求

“>”是访问成功的标志

可以参考这位博主的博客:

ESP8266获取网络时间 实时时钟-CSDN博客


//获取网络时间并解析给系统
void GetNet_Time(void)
{	
	if (failnum!=0)
	{
		failnum=0;
		WIFI_LOGO=HIDE;
		vTaskDelay(1000);
		//NetStatus=ESP_TLINK_INIT;//回去弄tlink看看是不是有网
	}else{
		uart2SendStr(time_keystr);  //发送GET请求	
		if(ESP12_WaitResponse(">", 10000) == 1){
			printf("\r\n time server connected!\r\n");
			NetStatus=ESP_TIME_CONNECTED;
			WIFI_LOGO=SHOW;failnum=0;
		}
	}
}

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值