esp12实现的网络时钟校准

news2024/12/23 11:02:13

网络时间的获取是通过向第三方服务器发送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;
		}
	}
}

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

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

相关文章

qt可点击的QLabel

需求——问题与思路 使用wpf实现一个可点击的超链接label相当简单&#xff08;如下图&#xff09;&#xff0c;但是qt的QLabel不会响应点击事件&#xff0c;那就从QLabel继承一个类&#xff0c;然后在该类中重写mousePressEvent函数&#xff0c;并在该函数中对左键点击事件做响…

人工智能——常用数学基础之线代中的矩阵

1. 矩阵的本质&#xff1a; 矩阵本质上是一种数学结构&#xff0c;它由按照特定规则排列的数字组成&#xff0c;通常被表示为一个二维数组。矩阵可以用于描述一组数据&#xff0c;或者表示某种关系&#xff0c;比如线性变换。 在人工智能中&#xff0c;矩阵常被用来表示数据集…

沉浸感拉满的三模游戏外设神器!谷粒金刚3 Pro游戏手柄开箱试玩

沉浸感拉满的三模游戏外设神器&#xff01;谷粒金刚3 Pro游戏手柄开箱试玩 哈喽小伙伴们好&#xff0c;我是Stark-C~ 对于喜欢打游戏的玩家来说&#xff0c;一款得力的游戏外设绝对是提升游戏体验&#xff0c;增加游戏乐趣的重要神器&#xff01;而在众多的外设中&#xff0c…

全同态加密在大模型应用中应用

密码学简介 上文的图例基本展示了常见加密体系。加密体系&#xff0c;如果用比较正式的描述方法&#xff0c;无疑是做了三件事&#xff1a; 首先&#xff0c;通过一个生成算法 &#x1d43e;&#x1d452;&#x1d466;&#x1d43a;&#x1d452;&#x1d45b;(1&#x1d70…

32.哀家要长脑子了!

1.299. 猜数字游戏 - 力扣&#xff08;LeetCode&#xff09; 公牛还是挺好数的&#xff0c;奶牛。。。妈呀&#xff0c;一朝打回解放前 抓本质抓本质&#xff0c;有多少位非公牛数可以通过重新排列转换公牛数字&#xff0c;意思就是&#xff0c;当这个数不是公牛数字时&#x…

ctfshow web入门 sqli-libs web552--web560

web552 宽字节注入 嗯原理我就不讲了&#xff0c;还是有点复杂后面有时间讲讲 总而言之就是用汉字把\的转义作用抵消了然后正常注入即可 ?id-1包 union select 1,2,3--?id-1包union select 1,(select group_concat(table_name) from information_schema.tables where tab…

ChatGPT-4o医学应用、论文撰写、数据分析与可视化、机器学习建模、病例自动化处理、病情分析与诊断支持

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT-3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年11月7日&#xff0c;OpenAI首届开发者大会被称为“科技界的春晚”&#xff0c;吸引了全球广大…

如何使用pytest组织自动化测试用例结构?

如何组织自动化测试工程的目录结构&#xff1f;这篇文章介绍了我是如何组织整个自动化工程目录结构的&#xff0c;本篇介绍下我是如何利用pytest框架组织一个测试用例文件的。 用例文件组织原则 整个testsuite目录下整体上按照特性模块划分目录&#xff0c;每个目录下可以只包…

Python容器 之 列表--下标和切片

列表的切片 得到是 新的列表字符串的切片 得到是 新的字符串 如果下标 不存在会报错 list1 [1, 3.14, "hello", False] print(list1)# 获取 列表中 第一个数据 print(list1[0]) # 1# 获取列表中的最后一个数据 print(list1[-1]) # [False]# 获取中间两个数 即 3.1…

币界网快讯,比特币7月份看牛预测

今日数字货币市场全面开启反弹&#xff0c;比特币从 60,000 美元大关飙升至 63,700 美元&#xff0c;预示着 7 月牛市的到来。在此之前&#xff0c;上周曾短暂跌破 60,000 美元&#xff0c;但受到 BTC 现货 ETF 流入的 7,300 万美元的推动——这是两周以来最大的流入。 BTC价格…

Linux下SUID提权学习 - 从原理到使用

目录 1. 文件权限介绍1.1 suid权限1.2 sgid权限1.3 sticky权限 2. SUID权限3. 设置SUID权限4. SUID提权原理5. SUID提权步骤6. 常用指令的提权方法6.1 nmap6.2 find6.3 vim6.4 bash6.5 less6.6 more6.7 其他命令的提权方法 1. 文件权限介绍 linux的文件有普通权限和特殊权限&a…

Redis基础教程(六):redis 哈希(Hash)

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

【火猫】cs2 donk登顶2024年上半年ADR榜

1、HLTV发布数据统计&#xff0c;donk以55张地图中96.8的ADR成功登顶上半年ADR榜单第一。紧随其后的是法国巨星ZywOo&#xff0c;以68图89.2的ADR排名第二。G2当家狙击手m0NESY以73图85的ADR排名第三。 2、白俄罗斯爆料人harumi透露&#xff1a;“Falcons战队向BOROS支付了6个月…

每日复盘-20240701

今日关注&#xff1a; 20240701 六日涨幅最大: ------1--------301182--------- 凯旺科技 五日涨幅最大: ------1--------300977--------- 深圳瑞捷 四日涨幅最大: ------1--------300977--------- 深圳瑞捷 三日涨幅最大: ------1--------300461--------- 田中精机 二日涨幅最…

科普:电脑硬件挑选

目录 一cpu 二主板 三内存 四硬盘 五显卡&#xff0c;散热&#xff0c;电源&#xff0c;机箱 六个人配置 一cpu 品牌&#xff1a;intel AMD 型号&#xff1a;I3,I5,I7 R7等 代数&#xff1a;换新不换旧 cpu后缀&#xff1a;k&#xff08;可超频&#xff09;f&#xf…

PHP电商系统开发指南最佳实践

电子商务系统开发的最佳实践包括&#xff1a;数据库设计&#xff1a;选择适合关系型数据库&#xff0c;优化数据结构&#xff0c;考虑表分区&#xff1b;安全&#xff1a;加密数据&#xff0c;防止 sql 注入&#xff0c;处理会话管理&#xff1b;用户界面&#xff1a;遵循 ux 原…

WhaleStudio 2.6正式发布,WhaleTunnel同步性能与连接器数量再创新高!

在这个数据驱动的大模型时代&#xff0c;数据集成的作用和意义愈发重要。数据不仅仅是信息的载体&#xff0c;更是推动企业决策和创新的关键因素。作为全球最流行的批流一体数据集成工具&#xff0c;WhaleTunnel随着WhaleStudio 2.6版本正式发布&#xff0c;带来了多项功能增强…

App测试技术(纯理论)

之前我们也学习过一些普通用例的设计, 如功能, 性能, 安全性, 兼容性, 易用性, 界面的测试用例设计, 之前我们讲的基本都是对于Web应用而言的, 这里我们来讲一下移动端的App测试用例设计. 功能方面 安装&卸载测试 这是只属于App的一类测试, 再平常我们使用移动设备(手机…

扩展学习|风险评估和风险管理:回顾其基础上的最新进展

文献来源&#xff1a;[1]Aven, T. (2016). Risk assessment and risk management: Review of recent advances on their foundation. European journal of operational research, 253(1), 1-13. 文章简介&#xff1a;大约30-40年前&#xff0c;风险评估和管理被确立为一个科学领…

Linux环境安装配置nginx服务流程

Linux环境的Centos、麒麟、统信操作系统安装配置nginx服务流程操作&#xff1a; 1、官网下载 下载地址 或者通过命令下载 wget http://nginx.org/download/nginx-1.20.2.tar.gz 2、上传到指定的服务器并解压 tar -zxvf nginx-1.20.1.tar.gzcd nginx-1.20.1 3、编译并安装到…