[GD32L233C-START 评测] 【GD32L233C-START评测】6. 获取RTC时间并通过OLED显示

hehung   2022-1-23 19:00 楼主

本文将讲解如何驱动RTC获取高精度时间并将时间通过OLED显示出来,关于OLED驱动可以参考我的上一篇帖子。

 

之前的帖子可以参考:

【GD32L233C-START评测】1.开箱

【GD32L233C-START评测】2.手把手创建新工程

【GD32L233C-START评测】3.移植FreeRTOS到GD32L233

【GD32L233C-START评测】4. 移植RT-Thread到GD32L233

【GD32L233C-START评测】5. IIC驱动OLED

 

1. 新建文件

新建app_rtc.c以及app_rtc.h并放到app文件夹下,将这两个文件添加到app组下

RTC相关的库文件主要存放在gd32l23x_rtc.c这个文件下。

1.png

 

2. RTC相关初始化与时间获取代码编写

初始化RTC需要时能RCU PMU和BKP时,并且配置RTC时钟为32KHz,还需要初始化时间,本例中初始化时间设置的为2022年1月23号17点40分0秒

注意:初始化的时间日期都需要使用16进制

下面是源代码,我单独编写了一个函数获取年月日时分秒,该函数为rtc_getDateAndTime(),可以给外部使用,主要是用来给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显示

OLED显示我是在main.c中做的

main.c中需要包含app_rtc.h

编写了一个静态函数,获取最新时间,然后使用sprintf()格式化在写到OLED中,通过OLED显示出时间。

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();
}

 

mian()函数实现如下:

先初始化RTC,然后每500ms刷新一次OLED,其实1s刷新一次就可以了。

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. 显示效果:

1642934822126.gif

 

 

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复