【GD32L233C-START Review】6. Get RTC time and display it through OLED
[Copy link]
This article will explain how to drive the RTC to obtain high-precision time and display the time through OLED. For more information about OLED driving, please refer to my previous post.
For previous posts, please refer to:
【GD32L233C-START Review】1. Unboxing
[GD32L233C-START Review] 2. Create a new project step by step
[GD32L233C-START Evaluation] 3. Porting FreeRTOS to GD32L233
【GD32L233C-START Review】4. Porting RT-Thread to GD32L233
【GD32L233C-START Review】5. IIC driving OLED
1. Create a new file
Create app_rtc.c and app_rtc.h and put them in the app folder, add these two files to the app group
RTC-related library files are mainly stored in the file gd32l23x_rtc.c.
2. RTC related initialization and time acquisition code writing
Initialize the RTC when needed, RCU PMU and BKP, and configure the RTC clock to 32KHz. You also need the initialization time. In this example, the initialization time is set to 17:40:00 on January 23, 2022
Note: The initialization time and date must be in hexadecimal.
Below is the source code. I wrote a separate function to get the year, month, day, hour, minute and second. The function is rtc_getDateAndTime(), which can be used externally, mainly to display the time on OLED.
app_rtc.c
#include <stdio.h>
#include "bmp.h"
#include "app_oled.h"
#include "systick.h"
#include "app_rtc.h"
#include "gd32l23x_rtc.h"
#define RTC_CLOCK_SOURCE_IRC32K
//#define RTC_CLOCK_SOURCE_LXTAL
#define BKP_VALUE 0x32F0
/* setup RTC time value */
/* Initial Date and Time */
DataTimeType InitTime = {
.year = 0x22,
.month = 0x1,
.day = 0x23,
.hour = 0x17,
.min = 0x40,
.sec = 0x00
};
/* Current Time */
DataTimeType rtc_currentTime;
static rtc_parameter_struct rtc_initpara;
static uint32_t prescaler_a = 0, prescaler_s = 0;
static void rtc_pre_config(void);
static void rtc_setup(void);
void RTC_Init(void)
{
/* enable PMU and BKP clock */
rcu_periph_clock_enable(RCU_PMU);
rcu_periph_clock_enable(RCU_BKP);
/* enable the access of the RTC registers */
pmu_backup_write_enable();
rtc_pre_config();
rtc_setup();
/* check if RTC has aready been configured */
// if (BKP_VALUE != RTC_BKP0){
// rtc_setup();
// }else{
// /* detect the reset source */
// if (RESET != rcu_flag_get(RCU_FLAG_PORRST)){
// printf("power on reset occurred....\n\r");
// }else if (RESET != rcu_flag_get(RCU_FLAG_EPRST)){
// printf("external reset occurred....\n\r");
// }
// printf("no need to configure RTC....\n\r");
//
// rtc_show_time();
// }
rcu_all_reset_flag_clear();
}
/*!
\brief RTC configuration function
\param[in] none
\param[out] none
\retval none
*/
static void rtc_pre_config(void)
{
#if defined (RTC_CLOCK_SOURCE_IRC32K)
rcu_osci_on(RCU_IRC32K);
rcu_osci_stab_wait(RCU_IRC32K);
rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);
prescaler_s = 0x13F;
prescaler_a = 0x63;
#elif defined (RTC_CLOCK_SOURCE_LXTAL)
rcu_osci_on(RCU_LXTAL);
rcu_osci_stab_wait(RCU_LXTAL);
rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
prescaler_s = 0xFF;
prescaler_a = 0x7F;
#else
#error RTC clock source should be defined.
#endif /* RTC_CLOCK_SOURCE_IRC32K */
rcu_periph_clock_enable(RCU_RTC);
rtc_register_sync_wait();
}
/*!
\brief use hyperterminal to setup RTC time and alarm
\param[in] none
\param[out] none
\retval none
*/
static void rtc_setup(void)
{
/* current time input */
printf("=======Configure RTC Time========\n\r");
rtc_initpara.factor_asyn = prescaler_a;
rtc_initpara.factor_syn = prescaler_s;
rtc_initpara.year = InitTime.year;
rtc_initpara.day_of_week = RTC_SUNDAY;
rtc_initpara.month = InitTime.month;
rtc_initpara.date = InitTime.day;
rtc_initpara.display_format = RTC_24HOUR;
rtc_initpara.am_pm = RTC_PM;
rtc_initpara.hour = InitTime.hour;
rtc_initpara.minute = InitTime.min;
rtc_initpara.second = InitTime.sec;
if(ERROR == rtc_init(&rtc_initpara))
{
printf("\n\r** RTC time configuration failed! **\n\r");
}else
{
printf("\n\r** RTC time configuration success! **\n\r");
rtc_show_time();
RTC_BKP0 = BKP_VALUE;
}
}
/*!
\brief display the current time
\param[in] none
\param[out] none
\retval none
*/
void rtc_show_time(void)
{
rtc_current_time_get(&rtc_initpara);
printf("Time:20%0.2x-%0.2x-%0.2x %0.2x:%0.2x:%0.2x\n", \
rtc_initpara.year, rtc_initpara.month , rtc_initpara.date,\
rtc_initpara.hour, rtc_initpara.minute, rtc_initpara.second);
}
/* Get Current Date-Time */
DataTimeType rtc_getDateAndTime(void)
{
rtc_current_time_get(&rtc_initpara);
rtc_currentTime.year = rtc_initpara.year;
rtc_currentTime.month = rtc_initpara.month;
rtc_currentTime.day = rtc_initpara.date;
rtc_currentTime.hour = rtc_initpara.hour;
rtc_currentTime.min = rtc_initpara.minute;
rtc_currentTime.sec = rtc_initpara.second;
return rtc_currentTime;
}
app_rtc.h
#ifndef __APP_RTC_H__
#define __APP_RTC_H__
#include <stdint.h>
/* Type for year, month, day, hour, min, sec */
typedef struct
{
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t min;
uint8_t sec;
} DataTimeType;
extern void RTC_Init(void);
extern DataTimeType rtc_getDateAndTime(void);
extern void rtc_show_time(void);
#endif
3. OLED display
I made the OLED display in main.c
app_rtc.h needs to be included in main.c
A static function is written to get the latest time, and then use sprintf() to format it and write it to the OLED to display the time.
static void OLED_ShowTime(void)
{
char currentDate[12];
char currentTime[12];
DataTimeType DateTime;
DateTime = rtc_getDateAndTime();
sprintf(currentDate, "20%0.2x-%0.2x-%0.2x", \
DateTime.year, DateTime.month , DateTime.day);
sprintf(currentTime, "%0.2x:%0.2x:%0.2x\n\r", \
DateTime.hour, DateTime.min, DateTime.sec);
OLED_ShowString(24, 32, (const uint8_t *)currentDate, 16, 1);
OLED_ShowString(24, 48, (const uint8_t *)currentTime, 16, 1);
OLED_Refresh_Gram();
}
The main() function is implemented as follows:
Initialize the RTC first, then refresh the OLED every 500ms. In fact, refreshing once every 1s is sufficient.
int main(void)
{
/* configure systick */
systick_config();
/* initilize the LEDs, USART and key */
gd_eval_led_init(LED1);
gd_eval_led_init(LED2);
gd_eval_com_init(EVAL_COM);
RTC_Init();
IIC_Init();
OLED_Init();
OLED_ShowString(0, 0, (const unsigned char*)"GD32L233C-START", 16, 1);
OLED_ShowString(24, 16, (const unsigned char*)"EEWORLD", 16, 1);
OLED_Refresh_Gram();
while(1)
{
OLED_ShowTime();
//rtc_show_time();
delay_1ms(500);
}
}
4. Display effect:
|