21-ESP32-S3实时时钟(RTC)

发布于:2024-05-05 ⋅ 阅读:(35) ⋅ 点赞:(0)

ESP32-S3实时时钟(RTC)的使用

ESP32-S3是一款高性能的Wi-Fi和蓝牙集成的系统级芯片(SoC),它包含一个实时时钟(RTC)模块,可以在系统的其他部分关闭时继续运行,以节省电能。下面是如何使用ESP32-S3的RTC模块的一些基本步骤。

RTC模块的基本功能

ESP32-S3的RTC模块具有以下主要功能:

  • 时间和日期:RTC模块可以提供实时的时间和日期信息。
  • 闹钟:可以设置RTC模块在特定的时间和日期发出信号。
  • 定时器:RTC模块可以作为一个定时器,用于在特定的时间间隔后发出信号。
  • 低功耗模式:当ESP32-S3的其他部分关闭时,RTC模块可以继续运行,以节省电能。

常用API

1.设置当前时间 settimeofday函数

settimeofday函数用于设置系统时间。它的原型如下:

int settimeofday(const struct timeval *tv, const struct timezone *tz);

其中,tv参数是一个指向timeval结构体的指针,该结构体包含了要设置的时间(以自Epoch(1970-01-01 00:00:00 +0000 (UTC))以来的秒数和微秒数)。tz参数在现代系统中通常被忽略,应设置为NULL。

如果函数执行成功,返回0;如果失败,返回-1,并设置errno以指示错误。

2.获取当前时间 localtime_r函数

localtime_r函数用于将time_t类型的时间(自Epoch以来的秒数)转换为本地时间表示的tm结构体。它的原型如下:

struct tm *localtime_r(const time_t *timer, struct tm *buf);

其中,timer参数是一个指向time_t类型的指针,表示要转换的时间;buf参数是一个指向tm结构体的指针,用于存储转换后的时间。

localtime_r函数是线程安全的,因为它使用用户提供的存储空间来存储结果,而不是使用静态存储空间。如果函数执行成功,返回指向结果的指针;如果失败,返回NULL。

3.设置时间环境变量

setenv是一个用于设置环境变量的函数。它的原型如下:

int setenv(const char *name, const char *value, int overwrite);

其中,name是要添加或修改的环境变量的名称,value是环境变量的新值,overwrite是一个标志,表示当环境变量name已经存在时是否覆盖其值。

  • 如果overwrite非零,那么无论环境变量name是否存在,都将其值设置为value
  • 如果overwrite为零,那么只有当环境变量name不存在时,才将其值设置为value

setenv函数返回0表示成功,返回-1表示失败。

例如,setenv("TZ", "CST-8", 1);这行代码的作用是设置环境变量TZ的值为CST-8,表示中国标准时间,即UTC+8。这样,当你获取或设置RTC模块的时间时,它就会按照中国标准时间来进行。

关于 协调时间时 的概念

UTC(Coodinated Universal Time),又称协调世界时,世界统一时间、世界标准时间、国际协调时间。由于英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。

UTC是现在全球通用的时间标准,全球各地都同意将各自的时间进行同步协调。UTC是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统。

UTC基于国际原子时,并通过不规则的加入闰秒来抵消地球自转变慢的影响。闰秒在必要的时候会被插入到UTC中,以保证协调世界时(UTC)与世界时(UT1)相差不超过0.9秒。

如何设置RTC模块

写一个示例,设置当前时间然后获取当前时间 打在串口上

#include <time.h>  // 引入时间库

void setup() {
  // 初始化串口
  Serial.begin(115200);  // 设置串口波特率为115200

  // 设置当前时间
  struct tm timeinfo;  // 定义一个tm结构体变量timeinfo
  timeinfo.tm_year = 2024 - 1900;  // 设置年份
  timeinfo.tm_mon = 5 - 1;  // 设置月份
  timeinfo.tm_mday = 2;  // 设置日期
  timeinfo.tm_hour = 13;  // 设置小时
  timeinfo.tm_min = 45;  // 设置分钟
  timeinfo.tm_sec = 30;  // 设置秒
  setenv("TZ", "CST-8", 1);  // 设置时区为中国标准时间
  tzset();  // 使时区设置生效
  const time_t now = mktime(&timeinfo);  // 将tm结构体转换为time_t格式
  struct timeval tv = { .tv_sec = now };  // 定义一个timeval结构体变量tv,并设置其秒数
  settimeofday(&tv, NULL);  // 设置系统时间

  // 获取并打印当前时间
  time_t now_get;  // 定义一个time_t变量now_get
  struct tm timeinfo_get;  // 定义一个tm结构体变量timeinfo_get
  time(&now_get);  // 获取当前时间
  localtime_r(&now_get, &timeinfo_get);  // 将time_t格式的时间转换为tm结构体格式
  Serial.print("Current time: ");  // 打印字符串"Current time: "
  Serial.print(timeinfo_get.tm_hour);  // 打印小时
  Serial.print(":");  // 打印冒号
  Serial.print(timeinfo_get.tm_min);  // 打印分钟
  Serial.print(":");  // 打印冒号
  Serial.println(timeinfo_get.tm_sec);  // 打印秒数并换行
}

void loop() {
  // 延时1秒
  delay(1000);  // 暂停1秒
}

这个示例首先在setup()函数中设置了当前时间为2024年5月2日13:45:30,然后立即获取并打印当前时间。这样,你就可以在串口监视器上看到设置的当前时间了。

🚨注意setenv("TZ", "CST-8", 1); 这行代码的作用是设置时区为中国标准时间。,setenv函数用于设置环境变量。这里,设置了TZ环境变量的值为CST-8,表示中国标准时间,即UTC+8。这样,当你获取或设置RTC模块的时间时,它就会按照中国标准时间来进行。如果你想设置为其他时区,只需将CST-8替换为相应的时区即可。例如,如果你想设置为美国东部标准时间,可以将CST-8替换为EST5EDT

🚨注意在C语言的tm结构体中,tm_year字段表示的是自1900年以来的年数,tm_mon字段表示的是月份,但是它的范围是0(一月)到11(十二月)。所以,当我们设置tm_yeartm_mon字段的值时,需要进行相应的调整:

  • 对于年份,我们需要从实际年份中减去1900。例如,我们想要设置年份为2024,那么tm_year应该设置为2024 - 1900

  • 对于月份,我们需要从实际月份中减去1。例如,如果我们想要设置月份为5月,那么tm_mon应该设置为5 - 1

这样,2024 - 19005 - 1就分别表示了年份2024和5月。

总结

参考资料

ESP-IDF 系统时间
微软copilot