Appearance
RTC时钟
esp32里面的RTC部件和SNTP服务可以用于获取时间
是顺着一个部分的时候
- esp32进行wifi的连接
- 使用SNTP网络时间库进行时间的校准
- 通过RTC库设置时区, 对获取的数据进行转换
- 使用time.h文件对时间进行转换
STNP
网络时间协议NTP的一个子集, 使用NTP协议可以获取准确的时间, 会自动获取可靠的服务器, 并且这一个架构有灵活的可扩展性以及很高的精度
使用SNTP的时候精度会有所下降
国内可用的NTP 服务器地址
1.cn.pool.ntp.org
2.cn.pool.ntp.org
3.cn.pool.ntp.org
0.cn.pool.ntp.org
cn.pool.ntp.org
tw.pool.ntp.org
0.tw.pool.ntp.org
1.tw.pool.ntp.org
2.tw.pool.ntp.org
3.tw.pool.ntp.org
esp32提供了sntp时钟同步的库,sntp获得的网络时间可以更新到esp32的系统时钟里面去
时间戳
使用NTP获取的时间戳是一个64位的数据, 前面32位是1970到现在的秒数, 后面的是小数
esp32的SNTP库会在内部调用settimeofday() and adjtime()来自动更新esp32的系统时间。这些两个函数的功能是,当收到来自NTP服务器的信息后,修改esp32的系统时间。
API函数
C语言
常用的结构
c
struct tm
{
int tm_sec; //秒
int tm_min; //分钟
int tm_hour; //当天的小时
int tm_mday; //每个月的日期
int tm_mon; //月份
int tm_year; //从1900年开始的年份
int tm_wday; //周几, 周日开始
int tm_yday; //每年的第几天
int tm_isdst; //Daylight Saving Time flag
};
clock_t 时钟数, 实际是一个long类型
time_t 从1900年1月1日0点UTC时间开始的时间, 实际是一个long类型。单位秒。
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
函数
函数 | 说明 |
---|---|
asctime | tm 转 string |
ctime | time_t 转 string |
gmtime | UTC时间的time_t 转 tm |
localtime | 本地时间的time_t 转 tm |
strftime | 格式化为string |
mktime | tm 转time_t |
c
char *asctime(const struct tm *timeptr);
返回一个方便读取的字符串格式的时间
cstruct tm { int tm_sec; /* 秒,范围从 0 到 59 */ int tm_min; /* 分,范围从 0 到 59 */ int tm_hour; /* 小时,范围从 0 到 23 */ int tm_mday; /* 一月中的第几天,范围从 1 到 31 */ int tm_mon; /* 月份,范围从 0 到 11 */ int tm_year; /* 自 1900 起的年数 */ int tm_wday; /* 一周中的第几天,范围从 0 到 6 */ int tm_yday; /* 一年中的第几天,范围从 0 到 365 */ int tm_isdst; /* 夏令时 */ };
c
time_t time(time_t *t);
获取时间, 返回值和传入参数都是返回值可以用于返回一个时间
c
int gettimeofday(struct timeval *tv, struct timezone *tz);
会把当前的时间使用第一个参数传递出来
第二个参数是用来计算时区的
cstruct timezone{ int tz_minuteswest;/*和greenwich时间差*/ int tz_dsttime; }
c
sock_t clock();
clock()函数的返回值就是你程序当前运行的时间(毫秒为单位)
sock_t实际是一个long类型的毫秒值
c
double difftime(time_t time2, time_t time1);
double difftime(time_t time1, time_t time2) 返回 time1 和 time2 之间相差的秒数 (time1 - time2)。这两个时间是在日历时间中指定的,表示了自纪元 Epoch(协调世界时 UTC:1970-01-01 00:00:00)起经过的时间。
c
struct tm *gmtime(const time_t *timeptr);
时间格式转换
c
struct tm * tmS = localtime(time_t * p);
localtime 将 time_t (从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数,是一个8字节长度的有符号整数)格式数据转化为tm的格式
c
time_t mktime(struct tm *timeptr);
格式转换
c
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)
根据 format 中定义的格式化规则,格式化结构 timeptr 表示的时间,并把它存储在 str 中。
说明符 替换为 实例 %a 缩写的星期几名称 Sun %A 完整的星期几名称 Sunday %b 缩写的月份名称 Mar %B 完整的月份名称 March %c 日期和时间表示法 Sun Aug 19 02:56:02 2012 %d 一月中的第几天(01-31) 19 %H 24 小时格式的小时(00-23) 14 %I 12 小时格式的小时(01-12) 05 %j 一年中的第几天(001-366) 231 %m 十进制数表示的月份(01-12) 08 %M 分(00-59) 55 %p AM 或 PM 名称 PM %S 秒(00-61) 02 %U 一年中的第几周,以第一个星期日作为第一周的第一天(00-53) 33 %w 十进制数表示的星期几,星期日表示为 0(0-6) 4 %W 一年中的第几周,以第一个星期一作为第一周的第一天(00-53) 34 %x 日期表示法 08/19/12 %X 时间表示法 02:50:06 %y 年份,最后两个数字(00-99) 01 %Y 年份 2012 %Z 时区的名称或缩写 CDT %% 一个 % 符号 %
c
int gettimeofday(struct timeval*tv,struct timezone *tz ); //获取时间
int settimeofday(const struct timeval *tv, const struct timezone *tz); //设置时间
SNTP时间同步
在获取SNTP时间以后会使用settimeofday进行设置时间
包括 SNTP 函数在内的一些 lwIP API 并非线程安全,因此建议在与 SNTP 模块交互时使用 esp_netif component。
- 要初始化特定的 SNTP 服务器并启动 SNTP 服务,只需创建有特定服务器名称的默认 SNTP 服务器配置,然后调用
esp_netif_sntp_init()
注册该服务器并启动 SNTP 服务。这一个函数会自动获取时间
c
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
esp_netif_sntp_init(&config);
- 等待获取时间
c
if (esp_netif_sntp_sync_wait(pdMS_TO_TICKS(10000)) != ESP_OK) {
printf("Failed to update system time within 10s timeout");
}
时区
要设置本地时区,请使用以下 POSIX 函数:
- 调用
setenv()
,将TZ
环境变量根据设备位置设置为正确的值。时间字符串的格式与 GNU libc 文档 中描述的相同(但实现方式不同)。 - 调用
tzset()
,为新的时区更新 C 库的运行数据。
完成上述步骤后,请调用标准 C 库函数 localtime()
。该函数将返回排除时区偏差和夏令时干扰后的准确本地时间。
c
setenv("TZ","UTC-08:00",1);