Skip to content

ESP_RTC CODE

Warning

Looks there is a builtin file named rtc.h in the ESP-IDF, so we need to name our file as esp_rtc.h to avoid conflicts. So as to the rtc.c file.

Component Architecture

- driver
    - esp_rtc
        - include
            - esp_rtc.h
        - esp_rtc.c
        - CMakeLists.txt

driver/esp_rtc/CMakeLists.txt

set(src_dirs
    .
)

set(include_dirs
    include
)

set(requires
)

idf_component_register(SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})

esp_rtc.h

/**
 * @file esp_rtc.h
 * ! Do not name as rtc.h, as it will conflict with the built-in rtc.h
 * @author
 * @brief Header file for the RTC driver
 * @version 1.0
 * @date 2024-11-18
 * @ref Alienteck RTC Driver
 * @copyright Copyright (c) 2024
 *
 */

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

/* Time structure, including year, month, day, week, hour, minute, and second */
typedef struct {
  uint8_t hour; /* Hour */
  uint8_t min;  /* Minute */
  uint8_t sec;  /* Second */
  /* Gregorian year, month, day, and week */
  uint16_t year; /* Year */
  uint8_t month; /* Month */
  uint8_t date;  /* Day */
  uint8_t week;  /* Weekday */
} _calendar_obj;

extern _calendar_obj calendar; /* Time structure */

/* Function declarations */
/**
 * @brief       Set the RTC time
 * @param       year    : Year
 * @param       mon     : Month
 * @param       mday    : Day
 * @param       hour    : Hour
 * @param       min     : Minute
 * @param       sec     : Second
 * @retval      None
 */
void rtc_set_time(int year, int mon, int mday, int hour, int min, int sec); /* Set time */

/**
 * @brief       Get the current time
 * @param       None
 * @retval      None
 */
void rtc_get_time(void); /* Get time */

/**
 * @brief       Convert year, month, and day to the day of the week
 * @note        Calculates the weekday based on the Gregorian calendar.
 *              Utilizes the Kim Larson formula for calculation.
 *              For more details, refer to:
 *              https://www.cnblogs.com/fengbohello/p/3264300.html
 * @param       year : Year
 * @param       month: Month
 * @param       day  : Day
 * @retval      0: Sunday; 1 ~ 6: Monday ~ Saturday
 */
uint8_t rtc_get_week(uint16_t year, uint8_t month, uint8_t day); /* Get the weekday */

#ifdef __cplusplus
}
#endif

esp_rtc.c

/**
 * @file esp_rtc.c
 * ! Do not name as rtc.c, as it will conflict with the built-in rtc.c
 * @author
 * @brief This file contains the implementation of the RTC driver
 * @version 1.0
 * @date 2024-11-18
 * @ref Alienteck RTC Driver
 *
 */

#include "esp_rtc.h"

#ifdef __cplusplus
extern "C" {
#endif

_calendar_obj calendar; /* Time structure */

/**
 * @brief       Set the RTC time
 * @param       year    : Year
 * @param       mon     : Month
 * @param       mday    : Day
 * @param       hour    : Hour
 * @param       min     : Minute
 * @param       sec     : Second
 * @retval      None
 */
void rtc_set_time(int year, int mon, int mday, int hour, int min, int sec) {
  struct tm datetime;
  /* Set time */
  datetime.tm_year = year - 1900;
  datetime.tm_mon = mon - 1;
  datetime.tm_mday = mday;
  datetime.tm_hour = hour;
  datetime.tm_min = min;
  datetime.tm_sec = sec;
  datetime.tm_isdst = -1;
  /* Get total seconds since 1970-01-01 */
  time_t second = mktime(&datetime);
  struct timeval val = {.tv_sec = second, .tv_usec = 0};
  /* Set current time */
  settimeofday(&val, NULL);
}

/**
 * @brief       Get the current time
 * @param       None
 * @retval      None
 */
void rtc_get_time(void) {
  struct tm* datetime;
  time_t second;
  /* Get the time elapsed since (1970-01-01 00:00:00 UTC) in seconds */
  time(&second);
  datetime = localtime(&second);

  calendar.hour = datetime->tm_hour; /* Hour */
  calendar.min = datetime->tm_min;   /* Minute */
  calendar.sec = datetime->tm_sec;   /* Second */
  /* Gregorian year, month, day, and week */
  calendar.year = datetime->tm_year + 1900; /* Year */
  calendar.month = datetime->tm_mon + 1;    /* Month */
  calendar.date = datetime->tm_mday;        /* Day */
  /* Weekday */
  calendar.week = rtc_get_week(calendar.year, calendar.month, calendar.date);
}

/**
 * @brief       Convert year, month, and day to the day of the week
 * @note        Calculates the weekday based on the Gregorian calendar.
 *              Utilizes the Kim Larson formula for calculation.
 *              For more details, refer to:
 *              https://www.cnblogs.com/fengbohello/p/3264300.html
 * @param       year : Year
 * @param       month: Month
 * @param       day  : Day
 * @retval      0: Sunday; 1 ~ 6: Monday ~ Saturday
 */
uint8_t rtc_get_week(uint16_t year, uint8_t month, uint8_t day) {
  uint8_t week = 0;

  if (month < 3) {
    month += 12;
    --year;
  }

  week =
      (day + 1 + 2 * month + 3 * (month + 1) / 5 + year + (year >> 2) - year / 100 + year / 400) %
      7;
  return week;
}

#ifdef __cplusplus
}
#endif

main.c

/**
 * @file main.c
 * @author SHUAIWEN CUI (SHUAIWEN001@e.ntu.edu.sg)
 * @brief
 * @version 1.0
 * @date 2025-08-20
 *
 * @copyright Copyright (c) 2024
 *
 */

/* DEPENDENCIES */
// ESP
#include "esp_chip_info.h"  // ESP32 Chip Info
#include "esp_flash.h"      // ESP32 Flash
#include "esp_log.h"        // ESP32 Logging
#include "esp_psram.h"      // ESP32 PSRAM
#include "esp_system.h"     // ESP32 System
#include "nvs_flash.h"      // ESP32 NVS

// FreeRTOS
#include "freertos/FreeRTOS.h"  // ESP32 FreeRTOS
#include "freertos/task.h"      // ESP32 FreeRTOS Task

// BSP
#include "esp_rtc.h"
#include "exit.h"
#include "led.h"

/* Global variables */
char* weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saterday"};

/**
 * @brief Entry point of the program
 * @param None
 * @retval None
 */
void app_main(void) {
  esp_err_t ret;
  uint8_t tbuf[40];
  uint8_t t = 0;

  ret = nvs_flash_init();

  if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
    ESP_ERROR_CHECK(nvs_flash_erase());
    ret = nvs_flash_init();
  }

  led_init();
  rtc_set_time(2025, 8, 21, 10, 58, 00);

  while (1) {
    t++;

    if ((t % 10) == 0) {
      rtc_get_time();
      sprintf((char*)tbuf, "Time:%02d:%02d:%02d", calendar.hour, calendar.min, calendar.sec);
      printf("Time:%02d:%02d:%02d\r\n", calendar.hour, calendar.min, calendar.sec);
      sprintf((char*)tbuf, "Date:%04d-%02d-%02d", calendar.year, calendar.month, calendar.date);
      printf("Date:%02d-%02d-%02d\r\n", calendar.year, calendar.month, calendar.date);
      sprintf((char*)tbuf, "Week:%s", weekdays[calendar.week - 1]);
    }

    if ((t % 20) == 0) {
      led_toggle();
    }

    vTaskDelay(100);
  }
}