RASC-based keil electronic clock production (Renesas RA) (7) - configure RTC clock and display time

overview

This article will explain in detail how to use e2studio to set and configure the real-time clock (RTC) of the Renesas microcontroller, so as to realize the calendar function and interrupt generated in one second, so as to output real-time data through the serial port.
The Real Time Clock (RTC) module is a time management peripheral mainly used to record and control the date and time. Different from the timer in the common microcontroller (MCU), the RTC clock provides two timing modes: date mode and timing mode. Common functions of the RTC clock include setting the time, setting alarms, configuring periodic interrupts, and starting or stopping operations.
By using the e2studio tool, we can easily configure the RTC on the Renesas microcontroller for high precision time and date management. In this article, we will focus on how to set the RTC clock calendar and generate a one-second interrupt, so that the serial port can print data in real time.

hardware preparation

First, you need to prepare a development board. Here I am preparing a development board with chip model R7FA2E1A72DFL:

insert image description here

insert image description here

video tutorial

https://www.bilibili.com/video/BV1AV41157au/

keil electronic clock production based on RASC (Renesas RA)----(5) drive LED digital tube

RTC configuration

点击Stacks->New Stack->Timers -> Realtime Clock(r_rtc)。

insert image description here

RTC attribute configuration

insert image description here

Among them, LOCO is an internal low-speed clock. It needs accurate timing or an external low-speed crystal oscillator Sub-clock.

insert image description here
insert image description here

set time

After starting the RTC, you need to set the current time for it. You can use the R_RTC_CalendarTimeSet(&g_rtc0_ctrl, &set_time) function to achieve this. The specific time parameters can be adjusted by modifying the set_time variable.
insert image description here

//RTC变量
/* rtc_time_t is an alias for the C Standard time.h struct 'tm' */
rtc_time_t set_time =
{
    
    
    .tm_sec  = 50,      /* 秒,范围从 0 到 59 */
    .tm_min  = 59,      /* 分,范围从 0 到 59 */
    .tm_hour = 23,      /* 小时,范围从 0 到 23*/
    .tm_mday = 29,       /* 一月中的第几天,范围从 0 到 30*/
    .tm_mon  = 11,      /* 月份,范围从 0 到 11*/
    .tm_year = 123,     /* 自 1900 起的年数,2023为123*/
    .tm_wday = 6,       /* 一周中的第几天,范围从 0 到 6*/
//    .tm_yday=0,         /* 一年中的第几天,范围从 0 到 365*/
//    .tm_isdst=0;        /* 夏令时*/
};

insert image description here

set periodic interrupt

If you want to use RTC to implement fixed-latency interrupts, you can use the R_RTC_PeriodicIrqRateSet(rtc_ctrl_t *const p_ctrl, rtc_periodic_irq_select_t const rate) function to achieve it. For example, to set a periodic interrupt of 1 second, you can use the following code:
R_RTC_PeriodicIrqRateSet(&g_rtc0_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);
Every time a periodic interrupt occurs, the system will trigger the event RTC_EVENT_PERIODIC_IRQ of the callback function.

Set calendar alarm time

After starting the RTC, you can set the calendar alarm time. The alarm time can be set by using the R_RTC_CalendarAlarmSet(&g_rtc0_ctrl, &set_alarm_time) function. The specific time parameters can be adjusted by modifying the set_alarm_time variable. The specific setting method is as follows.
In this example, we just set sec_match to 1, so every minute, when the seconds reaches 5 seconds, the alarm will fire. If you want to implement the function of ringing only once a day, you need to set min_match and hour_match to 1 at the same time.

//RTC闹钟变量
rtc_alarm_time_t set_alarm_time=
{
    
    
     .time.tm_sec  = 55,      /* 秒,范围从 0 到 59 */
     .time.tm_min  = 59,      /* 分,范围从 0 到 59 */
     .time.tm_hour = 23,      /* 小时,范围从 0 到 23*/
     .time.tm_mday = 29,       /* 一月中的第几天,范围从 1 到 31*/
     .time.tm_mon  = 11,      /* 月份,范围从 0 到 11*/
     .time.tm_year = 123,     /* 自 1900 起的年数,2023为123*/
     .time.tm_wday = 6,       /* 一周中的第几天,范围从 0 到 6*/

     .sec_match        =  1,//每次秒到达设置的进行报警
     .min_match        =  0,
     .hour_match       =  0,
     .mday_match       =  0,
     .mon_match        =  0,
     .year_match       =  0,
     .dayofweek_match  =  0,
    };

insert image description here

Callback

The events that can trigger the callback function are as follows. RTC_EVENT_PERIODIC_IRQ is a set real-time event, for example, once every 1s, and RTC_EVENT_ALARM_IRQ is an alarm clock event.
insert image description here

//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;
}

insert image description here
At the same time, turn on the RTC in the main program to set the time and alarm clock.

/**********************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;

insert image description here
At the same time, add printing and interrupt processing in the while loop of the main function, as well as the current time display.

           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 y %d m %d d %d h %d m %d s %d w\n",rtc_year+1900,rtc_month,rtc_day,rtc_hour,rtc_minute,rtc_second,rtc_week);

				//时间显示
               num1=rtc_hour/10;
               num2=rtc_hour%10;

               num3=rtc_minute/10;
               num4=rtc_minute%10;
           }
           if(rtc_alarm_flag)
           {
    
    
               rtc_alarm_flag=0;
               printf("/************************Alarm Clock********************************/\n");
           }

       R_BSP_SoftwareDelay(10U, BSP_DELAY_UNITS_MILLISECONDS);
       

insert image description here
For a quick start, turn off the nixie tube test.

insert image description here

Demonstration effect

Set to print the current time every 1 second, and set the alarm to ring at 10 seconds after 1 minute.
insert image description here

Replacement date display.
insert image description here

Digital tube display date

You can add a display in the main program to let the digital tube display the date.

               num1=rtc_hour/10;
               num2=rtc_hour%10;

               num3=rtc_minute/10;
               num4=rtc_minute%10;

insert image description here

main program

#include "hal_data.h"
#include <stdio.h>
#include "smg.h"
#include "timer_smg.h"

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER

//数码管变量
uint8_t num1=1,num2=4,num3=6,num4=8;//4个数码管显示的数值
uint8_t num_flag=0;//4个数码管和冒号轮流显示,一轮刷新五次


//RTC变量
/* rtc_time_t is an alias for the C Standard time.h struct 'tm' */
rtc_time_t set_time =
{
    
    
    .tm_sec  = 50,      /* 秒,范围从 0 到 59 */
    .tm_min  = 59,      /* 分,范围从 0 到 59 */
    .tm_hour = 23,      /* 小时,范围从 0 到 23*/
    .tm_mday = 29,       /* 一月中的第几天,范围从 0 到 30*/
    .tm_mon  = 11,      /* 月份,范围从 0 到 11*/
    .tm_year = 123,     /* 自 1900 起的年数,2023为123*/
    .tm_wday = 6,       /* 一周中的第几天,范围从 0 到 6*/
//    .tm_yday=0,         /* 一年中的第几天,范围从 0 到 365*/
//    .tm_isdst=0;        /* 夏令时*/
};


//RTC闹钟变量
rtc_alarm_time_t set_alarm_time=
{
    
    
     .time.tm_sec  = 58,      /* 秒,范围从 0 到 59 */
     .time.tm_min  = 59,      /* 分,范围从 0 到 59 */
     .time.tm_hour = 23,      /* 小时,范围从 0 到 23*/
     .time.tm_mday = 29,       /* 一月中的第几天,范围从 1 到 31*/
     .time.tm_mon  = 11,      /* 月份,范围从 0 到 11*/
     .time.tm_year = 123,     /* 自 1900 起的年数,2023为123*/
     .time.tm_wday = 6,       /* 一周中的第几天,范围从 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;
}


fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
    
    
    if(p_args->event == UART_EVENT_TX_COMPLETE)
    {
    
    
        uart_send_complete_flag = true;
    }
}

#ifdef __GNUC__                                 //串口重定向
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
    
    
        err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
        if(FSP_SUCCESS != err) __BKPT();
        while(uart_send_complete_flag == false){
    
    }
        uart_send_complete_flag = false;
        return ch;
}

int _write(int fd,char *pBuffer,int size)
{
    
    
    for(int i=0;i<size;i++)
    {
    
    
        __io_putchar(*pBuffer++);
    }
    return size;
}





/*******************************************************************************************************************//**
 * 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 */

    /* Open the transfer instance with initial configuration. */
       err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
       assert(FSP_SUCCESS == err);



/**********************数码管测试***************************************/
//              ceshi_smg();
/**********************定时器开启***************************************/
    /* Initializes the module. */
    err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    /* Start the timer. */
    (void) R_GPT_Start(&g_timer0_ctrl);


/**********************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;


       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 y %d m %d d %d h %d m %d s %d w\n",rtc_year+1900,rtc_month,rtc_day,rtc_hour,rtc_minute,rtc_second,rtc_week);

                //时间显示
               num1=rtc_hour/10;
               num2=rtc_hour%10;

               num3=rtc_minute/10;
               num4=rtc_minute%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
}

Guess you like

Origin blog.csdn.net/qq_24312945/article/details/132131310