很高兴收到瑞萨电子发放的RA4L1开发板,这个板子上带了一个非常好的段码屏LCD,搭配这个屏可以做成万年历,显示时分秒实时时间。比如现在时间是16:20:23,含义就是16时20分23秒。刚好可以显示在段码屏上,6个数码管。如果要显示年月日的话,可以做成两屏,通过按键进行切换,一个屏显示年月日,下一个屏显示时分秒!!!
上面就是基本原理,只要理解了,就可以实现这样的功能。
这里核心功能就是需要使用到RTC模块。RA4L1板载RTC模块,可以获取实时时钟。
好的,话不多说,直接上干货!!
1。打开瑞萨的smart配置软件
按照上面的配置设置好RTC参数
2。设置串口
上面是串口参数
3。添加核心代码
#include "hal_data.h"
#include "usart9.h"
#include "RTT.h"
#include "led.h"
#include <stdio.h>
#include <stdlib.h>
#include "coremark.h"
#include "ebtn_app.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER
void coremark_main(void);
volatile uint8_t button_count = 0;
//RTC变量
/* rtc_time_t is an alias for the C Standard time.h struct 'tm' */
rtc_time_t set_time =
{
.tm_sec = 00, /* 秒,范围从 0 到 59 */
.tm_min = 05, /* 分,范围从 0 到 59 */
.tm_hour = 16, /* 小时,范围从 0 到 23*/
.tm_mday = 10, /* 一月中的第几天,范围从 1 到 31*/
.tm_mon = 6, /* 月份,范围从 0 到 11*/
.tm_year = 125, /* 自 1900 起的年数,2025为125*/
.tm_wday = 2, /* 一周中的第几天,范围从 0 到 6*/
// .tm_yday=0, /* 一年中的第几天,范围从 0 到 365*/
// .tm_isdst=0; /* 夏令时*/
};
//RTC闹钟变量
rtc_alarm_time_t set_alarm_time=
{
.time.tm_sec = 10, /* 秒,范围从 0 到 59 */
.time.tm_min = 30, /* 分,范围从 0 到 59 */
.time.tm_hour = 16, /* 小时,范围从 0 到 23*/
.time.tm_mday = 10, /* 一月中的第几天,范围从 1 到 31*/
.time.tm_mon = 6, /* 月份,范围从 0 到 11*/
.time.tm_year = 125, /* 自 1900 起的年数,2025为125*/
.time.tm_wday = 2, /* 一周中的第几天,范围从 0 到 6*/
.sec_match = 1,
.min_match = 0,
.hour_match = 0,
.mday_match = 0,
.mon_match = 0,
.year_match = 0,
.dayofweek_match = 0,
};
//RTC回调函数
volatile bool rtc_flag = 0;//RTC延时1s标志位
volatile bool rtc_alarm_flag = 0;//RTC闹钟
/* Callback function */
void rtc_callback(rtc_callback_args_t *p_args)
{
/* TODO: add your own code here */
if(p_args->event == RTC_EVENT_PERIODIC_IRQ)
rtc_flag=1;
else if(p_args->event == RTC_EVENT_ALARM_IRQ)
rtc_alarm_flag=1;
}
void disp_0(void);
void disp_1(void);
void disp_2(void);
void disp_3(void);
void disp_4(void);
void disp_5(void);
void disp_6(void);
void disp_7(void);
void disp_8(void);
void disp_9(void);
void disp_num(uint8_t channel, uint8_t num);
void disp_num1(uint8_t channel, uint8_t num);
void disp_COL1(void);
void disp_DOT1(void);
/*******************************************************************************************************************//**
main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function
is called by main() when no RTOS is used.
**********************************************************************************************************************/
void hal_entry(void)
{
/* TODO: add your own code here */
fsp_err_t err;
/* Open SLCDC driver */
err = R_SLCDC_Open(&g_slcdc0_ctrl, &g_slcdc0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* When using internal boost mode this delay is required to allow the boost circuit to charge. See RA4M1 User's
Manual (R01UH0887EJ0100) 8.2.18 "Segment LCD Source Clock Control Register (SLCDSCKCR)" for details. */
R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
/* Start SLCDC output */
err = R_SLCDC_Start(&g_slcdc0_ctrl);
assert(FSP_SUCCESS == err);
/* Set Display Area of SLCDC driver.*/
// err = R_SLCDC_SetDisplayArea(&g_slcdc0_ctrl, SLCDC_DISP_A);
// assert(FSP_SUCCESS == err);
//准备并写入段显示数据,第一个数码管显示1
uint8_t segment_data_num1[] = {
0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,
0x00,0x6
};
R_SLCDC_Write(&g_slcdc0_ctrl, 0, segment_data_num1, sizeof(segment_data_num1));
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
//准备并写入段显示数据,第二个数码管显示2
uint8_t segment_data_num2[] = {
0xE,0x3};
R_SLCDC_Write(&g_slcdc0_ctrl, 15, segment_data_num2, sizeof(segment_data_num2));
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
//准备并写入段显示数据,第三个数码管显示3
R_SLCDC_Modify(&g_slcdc0_ctrl, 22, 0xA, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 23, 0x7, 0xF);
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
//准备并写入段显示数据,第四个数码管显示4
R_SLCDC_Modify(&g_slcdc0_ctrl, 24, 0x3, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 29, 0x6, 0xF);
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
//准备并写入段显示数据,第五个数码管显示5
R_SLCDC_Modify(&g_slcdc0_ctrl, 30, 0xB, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 39, 0x5, 0xF);
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
//准备并写入段显示数据,第六个数码管显示6
R_SLCDC_Modify(&g_slcdc0_ctrl, 40, 0xF, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 41, 0x5, 0xF);
R_BSP_SoftwareDelay (100, BSP_DELAY_UNITS_MILLISECONDS);
UART9_Init();
hal_systick_init();
ebtn_APP_Key_INIT();
/ RTC开启 *****************/
/* Initialize the RTC module*/
err = R_RTC_Open(&g_rtc0_ctrl, &g_rtc0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Set the RTC clock source. Can be skipped if "Set Source Clock in Open" property is enabled. */
R_RTC_ClockSourceSet(&g_rtc0_ctrl);
/* R_RTC_CalendarTimeSet must be called at least once to start the RTC */
R_RTC_CalendarTimeSet(&g_rtc0_ctrl, &set_time);
/* Set the periodic interrupt rate to 1 second */
R_RTC_PeriodicIrqRateSet(&g_rtc0_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);
R_RTC_CalendarAlarmSet(&g_rtc0_ctrl, &set_alarm_time);
uint8_t rtc_second = 0; //秒
uint8_t rtc_minute = 0; //分
uint8_t rtc_hour = 0; //时
uint8_t rtc_day = 0; //日
uint8_t rtc_month = 0; //月
uint16_t rtc_year = 0; //年
uint8_t rtc_week = 0; //周
rtc_time_t get_time;
printf("\r\n欢迎来到瑞萨电子\r\n");
printf("很高兴试用RA4L1开发板********\r\n");
printf("串口输出打印 波特率115200\r\n\r\n");
//清空0-41段
uint8_t segment_data_num_off[41+1] ;
for(int i=0;i<=41;i++)
segment_data_num_off[i]=0;
R_SLCDC_Write(&g_slcdc0_ctrl, 0, segment_data_num_off, sizeof(segment_data_num_off));
R_BSP_SoftwareDelay (1000, BSP_DELAY_UNITS_MILLISECONDS);
/*
//全部点亮
uint8_t segment_data_num_on[41+1] ;
for(int i=0;i<=41;i++)
segment_data_num_on[i]=0xf;
R_SLCDC_Write(&g_slcdc0_ctrl, 0, segment_data_num_on, sizeof(segment_data_num_on));
R_BSP_SoftwareDelay (1000, BSP_DELAY_UNITS_MILLISECONDS);
*/
while (1)
{
if(rtc_flag)
{
R_RTC_CalendarTimeGet(&g_rtc0_ctrl, &get_time);//获取RTC计数时间
rtc_flag=0;
rtc_second = get_time.tm_sec; //秒
rtc_minute = get_time.tm_min; //分
rtc_hour = get_time.tm_hour; //时
rtc_day = get_time.tm_mday; //日
rtc_month = get_time.tm_mon; //月
rtc_year = get_time.tm_year; //年
rtc_week = get_time.tm_wday; //周
printf("现在时间 %d 年 %d 月 %d 日 %d 时 %d 分 %d 秒 第 %d 周\n",rtc_year+1900,rtc_month+1,rtc_day,rtc_hour,rtc_minute,rtc_second,rtc_week);
disp_num(1, rtc_hour/10);disp_num(2, rtc_hour%10);
disp_num(3, rtc_minute/10);disp_num(4, rtc_minute%10);
disp_num(5, rtc_second/10);disp_num(6, rtc_second%10);
}
if(rtc_alarm_flag)
{
rtc_alarm_flag=0;
printf("/************************Alarm Clock********************************/\\n");
}
R_BSP_SoftwareDelay(10U, BSP_DELAY_UNITS_MILLISECONDS);
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
到此初始化完成
下面是RTC和段码显示屏核心功能函数,用来显示实时时间
先清空断码屏数据
while (1)
{
if(rtc_flag)
{
R_RTC_CalendarTimeGet(&g_rtc0_ctrl, &get_time);//获取RTC计数时间
rtc_flag=0;
rtc_second = get_time.tm_sec; //秒
rtc_minute = get_time.tm_min; //分
rtc_hour = get_time.tm_hour; //时
rtc_day = get_time.tm_mday; //日
rtc_month = get_time.tm_mon; //月
rtc_year = get_time.tm_year; //年
rtc_week = get_time.tm_wday; //周
printf("现在时间 %d 年 %d 月 %d 日 %d 时 %d 分 %d 秒 第 %d 周\\n",rtc_year+1900,rtc_month+1,rtc_day,rtc_hour,rtc_minute,rtc_second,rtc_week);
disp_num(1, rtc_hour/10);disp_num(2, rtc_hour%10);
disp_num(3, rtc_minute/10);disp_num(4, rtc_minute%10);
disp_num(5, rtc_second/10);disp_num(6, rtc_second%10);
}
if(rtc_alarm_flag)
{
rtc_alarm_flag=0;
printf("/************************Alarm Clock********************************/\\n");
}
R_BSP_SoftwareDelay(10U, BSP_DELAY_UNITS_MILLISECONDS);
}
打开串口查看数据
和电脑右下角时间完全吻合
详细细节,看我视频即可!!!!!!
——————————————————————————————————————————————————————
好了,我有完美了这个RTC实时时钟,做成了万年历,可以显示年月日,时分秒了。
原理是:我做了分屏切换,开机默认显示年月日,通过按键进行切换到时分秒,重复按键进行年月日时分秒循环切换!非常的完美了
详细代码如下:
while (1)
{
if(rtc_flag)
{
R_RTC_CalendarTimeGet(&g_rtc0_ctrl, &get_time);//获取RTC计数时间
rtc_flag=0;
rtc_second = get_time.tm_sec; //秒
rtc_minute = get_time.tm_min; //分
rtc_hour = get_time.tm_hour; //时
rtc_day = get_time.tm_mday; //日
rtc_month = get_time.tm_mon; //月
rtc_year = get_time.tm_year; //年
rtc_week = get_time.tm_wday; //周
printf("现在时间 %d 年 %d 月 %d 日 %d 时 %d 分 %d 秒 第 %d 周\n",rtc_year+1900,rtc_month,rtc_day,rtc_hour,rtc_minute,rtc_second,rtc_week);
year = rtc_year+1900;
year %= 100;
if((time_count %2) == 0)//年月日
{
disp_num(1, year/10);disp_num(2, year%10);
disp_num(3, rtc_month/10);disp_num(4, rtc_month%10);
disp_num(5, rtc_day/10);disp_num(6, rtc_day%10);
}
if((time_count %2) == 1)//时分秒
{
disp_num(1, rtc_hour/10);disp_num(2, rtc_hour%10);
disp_num(3, rtc_minute/10);disp_num(4, rtc_minute%10);
disp_num(5, rtc_second/10);disp_num(6, rtc_second%10);
}
}
if(rtc_alarm_flag)
{
rtc_alarm_flag=0;
printf("/************************Alarm Clock********************************/\n");
}
R_BSP_SoftwareDelay(10U, BSP_DELAY_UNITS_MILLISECONDS);
通过按键来进行年月日和时分秒的切换,完美了!!!此贴终结
下面是2025年6月10日
下面是17时23分19秒
看底部视频
更多回帖