ESP32超详细学习记录:NTP同步时间

本来想从开源项目找找灵感的,但是!那些代码真烂!!!!!

开源项目免不了的就是抄抄抄代码,想知道 NTP 是怎么实现的还要读那一堆烂代码,烦!

就算开源项目能怎么样!不还是一样的  烂!代!码!

自己想办法看看 NTP 的相关库是怎么实现的吧。


可以使用 aliyun 的 NTP 服务器。

发现不少开源项目都是用的 aliyun 的 NTP 服务器。

阿里云NTP服务器 - 云服务器 ECS - 阿里云https://help.aliyun.com/document_detail/92704.html


什么是NTP

NTP:Network Time Protocol(网络时间协议)

▶️ NTP 是用于同步网络中计算机时间的协议。它的用途是把计算机的时钟同步到世界协调时UTC。

UTC:Universal Time Coordinated(协调世界时)以原子时秒长为基础。

GMT:Universal Time(世界时)以地球自转为基础。

北京时间采用东八区的区时作为标准时间。北京时间比世界时(UTC)早8小时,北京时间=UTC+8。


使用 NTPClient 库获取时间

▶️ 如果使用 NTPClient 库,其实很简单很简单很简单!!

官方例程里就几个函数就实现了!就四个!

WiFiUDP ntpUDP;    //创建UDP实例

NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 60 * 60 * 8, 60000);    //NTC
    //UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval

//初始化函数
timeClient.begin();

//获取时间
timeClient.update();
timeClient.getFormattedTime();

这样,就能直接获取 小时:分钟:秒 的格式的时间了。

有感而发:学习ESP32还是要学一学网络协议啊!

需要说明的函数:

NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 60 * 60 * 8, 60000);    //NTC
    //UDP& udp, const char* poolServerName, long timeOffset, unsigned long updateInterval
  • ntpUDP:UDP实例

  • "europe.pool.ntp.org":NTP服务器地址

  • 60 * 60 * 8:是换算为东八区的时间需要的参数:秒*分钟*小时

  • 60000:更新时间

在库接口中,只看到了星期、时、分、秒的接口!没有年、月、日。

#include <WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>

const char *ssid     = "<SSID>";
const char *password = "<PASSWORD>";

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000);

void setup()
{
  Serial.begin(115200);

  WiFi.begin(ssid, password);

  while ( WiFi.status() != WL_CONNECTED ) 
  {
    delay ( 500 );
    Serial.print ( "." );
  }

  timeClient.begin();
}

void loop() 
{
  timeClient.update();
  Serial.println(timeClient.getFormattedTime());


  delay(1000);
}

如果想隔一段时间调用一次这种类似时间中断的功能,可引用 Ticker 库实现定时器功能。


ESP32核心库函数

在 ESP32 的核心文件夹下有 time.c 文件。定义了 configTime 函数用来配置时间。不需要引用头文件可以直接调用函数。

void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3)
  • gmtOffset_sec:世界时偏移量
  • daylightOffset_sec:时间偏移
  • server:服务器地址

在 time.c 文件中,还提供了其他的时间设置函数,包括设置时区、获取时区时间等等。

▶️ 获取本地时间,函数同样定义在 time.c 中,但是使用此函数需要 tm 类型的结构体存储时间!

tm 是定义在 C++ 库 time.h 中的结构体。

struct tm - C++ Referencehttps://cplusplus.com/reference/ctime/tm/

struct tm 
{  
//以下为常规日期
int tm_year;	/* 年份,其值从1900开始 */ 
int tm_mon;		/* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */  
int tm_mday;   	/* 一个月中的日期 - 取值区间为[1,31] */  
int tm_hour;	/* 时 - 取值区间为[0,23] */ 
int tm_min;		/* 分 - 取值区间为[0,59] */   
int tm_sec;		/* 秒–取值区间为[0,59] */   

int tm_wday;	/* 星期–取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */  
int tm_yday;	/* 从每年的1月1日开始的天数–取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */  
int tm_isdst;	/* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/  

long int tm_gmtoff;	 /*指定了日期变更线东面时区中UTC东部时区正秒数或UTC西部时区的负秒数*/   
const char *tm_zone;     /*当前时区的名字(与环境变量TZ有关)*/  
}; 

▶️ 如果是中国时间,需要注意的是年、月的时间问题!

函数示例:

此处函数参考了:Getting Date & Time From NTP Server With ESP32

#include "Arduino.h"
#include <WiFi.h>
#include "time.h"    // 为了使用tm结构体

const char* ssid       = "<SSID>";
const char* password   = "<PASSWORD>";

struct tm timeinfo;
 
void setup()
{
  Serial.begin(115200);
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) 
  {
      delay(500);
      Serial.print(".");
  }
  Serial.println(" CONNECTED");
  
  configTime(60*60*8, 0, "ntp3.aliyun.com");    // 用的阿里云的服务器
  printLocalTime();

  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF); 
}
 
void loop()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo))
   {
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %Y-%m-%d %H:%M:%S");
  delay(1000);
}

不出意外的情况下,会在串口打印如下类似信息:


也可以通过读取结构体的情况,取得

year = timeinfo.tm_year + 1900;    // 年份从1900开始
month = timeinfo.tm_mon + 1;    // 0表示1月
week = timeinfo.tm_wday;    // 这里要注意这是返回的数字,并不是单词!
...

但是这种办法不能自动更新时间,就比较烦一点点!可以加 Ticker 来进行定时执行获取时间。


不使用NTP获取时间的方法:API

其实和前面获取心知天气的文章使用相同的方法

心知天气天气状况获取,ESP32获取天气信息(含源码)_喜暖知寒的博客-CSDN博客_esp32获取天气ESP32获取天气信息https://blog.csdn.net/qq_41650023/article/details/124697234在网上找到了几个 API 的接口:

例如心知天气API返回的JSON数据:

苏宁返回的数据:http://quan.suning.com/getSysTime.do


甚至还能查网站的 GET 请求获取某些网站API

例如网站:现在北京时间 在线标准北京时间校对

在此网站找到了 GET 请求接口

可发现请求时间的 API 就是这个了:https://www.beijing-time.org/t/time.asp

请求返回值:

有些网站的 API 比较好找,有些比较难找。在此只是提供一个想法!


😄 最后就结束了啊 ~

其实没什么难的吧 ~ !

了解一下后才发现 NTP 这种东西在 ESP32 for Arduino 上这么好实现,以前以为不好实现还恐惧了好久呢 !

本篇文章也就是提供一个思路,附上了两个实现方式的完整代码,测试是可用的!应该要是应用的话会有BUG,不过那都不重要了。

OK,本篇文章如果有幸被小伙伴看到的话,希望对你有所帮助。

今日份开心哦 ~ 学到了心的知识 ~

会持续更新关于 ESP32 for Arduino 的一些小知识点哦 ~ 因为最近也在抽时间学一学!

如果本篇文章给您带来一些帮助,不妨 ~ 或者是 !~

要是同样初学的小伙伴,也不方便关注一下本专栏有关 ESP32 for Arduino 的其他文章哦 ~ 都是最为自己的笔记写的,相信会对你有所帮助!

  • 9
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ESP8266可以通过与NTP服务器进行通信来同步时间。在Arduino中,可以使用NTPClient库来实现这一功能。首先,需要在Arduino IDE的库管理器中下载并安装NTPClient库。然后,可以使用以下代码来同步NTP服务器时间: 1. 设置时区和NTP服务器地址: ```c sntp_set_timezone(user_param.timeZone); sntp_setservername(0, "0.cn.pool.ntp.org"); sntp_setservername(1, "1.cn.pool.ntp.org"); sntp_setservername(2, "2.cn.pool.ntp.org"); ``` 这里的`user_param.timeZone`可以是你所在地的时区设置,比如中国的时区是UTC+8。 2. 初始化SNTP(Simple Network Time Protocol): ```c sntp_init(); ``` 这将启动SNTP客户端并连接到NTP服务器。 3. 通过SNTP获取时间戳: ```c u32 time = sntp_get_current_timestamp(); ``` 这将返回当前的时间戳。如果成功获取到时间戳,可以使用以下代码将其转化为可读的日期和时间: ```c sntp_tm ****; char *string; sntp_tm real_tm; *** = sntp_get_real_tm(time); string = sntp_get_real_time(time); ``` 在上述代码中,`tm`是指向`sntp_tm`结构的指针,它包含了日期和时间详细信息。`string`是一个字符串,它表示时间的可读形式。 综上所述,通过以上步骤,ESP8266可以实现与NTP服务器的时间同步。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [esp8266 时间同步实现](https://blog.csdn.net/zsj1126/article/details/81220903)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [ESP8266同步NTP服务器时间](https://blog.csdn.net/weixin_42880082/article/details/119137727)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值