2025 / 07 / 03
【瑞萨RA2L1入门学习】RTC日历及串口设置时间

作者:VR小杰


1. 前言

本次实验内容是调用RTC实时时钟,实现日历、串口设定时间的功能。


2. 硬件部分

RTC

RTC 时钟模块是一个时间外设,主要用于日期时间的存储和控制,有别于一般 MCU中的 Timer,RTC 时钟有两种计时模式,日期模式和计时模式,RTC 常见的操作包括设置时间、设置定时闹铃、配置周期性中断以及启动或停止操作。


3. 软件部分

3.1 配置RTC

选择Stacks选项卡





配置完成后,生成项目代码。


3.2编写代码

将先前的项目模板复制一份,重命名为03_RTC


3.2.1 新建rtc.h

新建文件rtc.h,加入以下代码

#ifndef RTC_H_
#define RTC_H_
#include "hal_data.h"
extern rtc_time_t set_time;
extern volatile bool rtc_flag;
#endif


3.2.2 新建rtc.c

这段代码定义一个set_time结构体,用于在主函数中配置,同时实现了rtc_callback回调函数,用于每1秒中断一次使用

#include "hal_data.h"
#include "rtc.h"

rtc_time_t set_time = {
    .tm_sec = 59,   /* 秒,范围从 0 到 59 */
    .tm_min = 59,   /* 分,范围从 0 到 59 */
    .tm_hour = 23,  /* 小时,范围从 0 到 23*/
    .tm_mday = 28,  /* 一月中的第几天,范围从 1 到 31*/
    .tm_mon = 1,   /* 月份,范围从 0 到 11(0代表1月,11代表12月)*/
    .tm_year = 125, /* 自 1900 起的年数,2021 为 121*/
};

volatile bool rtc_flag = false;       // RTC 延时 1s 标志位

void rtc_callback(rtc_callback_args_t *p_args)
{
    if (p_args->event == RTC_EVENT_PERIODIC_IRQ)
        rtc_flag = true;
}


3.2.3 修改hal_entry.c

在文件开头加入代码

#include "rtc.h"

rtc_time_t get_time;


hal_entry函数中加入代码,主要功能是初始化了rtc、配置时间以及解析串口接收到的设定时间的信息

g_rtc0.p_api->open(&g_rtc0_ctrl, &g_rtc0_cfg);
    g_rtc0.p_api->calendarTimeSet(&g_rtc0_ctrl, &set_time);
    g_rtc0.p_api->periodicIrqRateSet(&g_rtc0_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);
    while (1)
    {
        if (rtc_flag)
        {
            g_rtc0.p_api->calendarTimeGet(&g_rtc0_ctrl, &get_time); // 获取 RTC 计数时间
            rtc_flag = 0;
            printf("%d年%d月%d日 %d:%d:%d\n",
                    get_time.tm_year + 1900, get_time.tm_mon +1, get_time.tm_mday,
                    get_time.tm_hour, get_time.tm_min, get_time.tm_sec);
        }
        if (uart_rx_complete_flag)
        {
            char * time;
            uart_rx_complete_flag = 0;
            // 解析设置时间的命令 e.g: time:20250126080910
            // warning: 未添加错误纠正算法,请输入正确的时间,否则工作异常!
            if(strncmp(rx_data, "time:", 5) == 0){
                time = rx_data+5;
                set_time.tm_year = ((time[0]-'0')*1000)+((time[1]-'0')*100)+
                        ((time[2]-'0')*10)+(time[3]-'0')-1900;
                set_time.tm_mon = ((time[4]-'0')*10)+(time[5]-'0') - 1;
                set_time.tm_mday = ((time[6]-'0')*10)+(time[7]-'0');
                set_time.tm_hour = ((time[8]-'0')*10)+(time[9]-'0');
                set_time.tm_min = ((time[10]-'0')*10)+(time[11]-'0');
                set_time.tm_sec = ((time[12]-'0')*10)+(time[13]-'0');
                g_rtc0.p_api->calendarTimeSet(&g_rtc0_ctrl, &set_time);
           }
        }
    }


3.2.4 修改debug_bsp_uart.c

改动部分比较多,为了方便起见,把该文件的内容都放在下方了。

#include "debug_bsp_uart.h"
/* 发送完成标志 */
volatile int uart_send_complete_flag = 0;
volatile int uart_rx_complete_flag = 0;

char rx_data[1024];
volatile uint16_t cnt;
uint8_t stat = 0;
/* 调试串口 UART9 初始化 */
void Debug_UART9_Init(void)
{
   fsp_err_t err = FSP_SUCCESS;

   err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
   assert(FSP_SUCCESS == err);
}

/* 串口中断回调 */
void debug_uart9_callback(uart_callback_args_t *p_args)
{
   switch (p_args->event)
   {
   case UART_EVENT_RX_CHAR:
   {
      /* 把串口接收到的数据发送回去 */
      // R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&(p_args->data), 1);
      rx_data[cnt++] = (char)p_args->data;
      if (stat == 0 && p_args->data == '\r')
      {
         stat = 1;
      }
      else if (stat == 1 && p_args->data == '\n')
      { // 接收完一行
         uart_rx_complete_flag = 1;
         cnt = 0;
      }
      else
      {
         stat = 0;
      }

      break;
   }
   case UART_EVENT_TX_COMPLETE:
   {
      uart_send_complete_flag = 1;
      break;
   }

   default:
      break;
   }
}

/* 重定向 printf 输出 */
#if defined __GNUC__ && !defined __clang__
int _write(int fd, char *pBuffer, int size); // 防止编译警告
int _write(int fd, char *pBuffer, int size)
{
   (void)fd;
   R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)pBuffer, (uint32_t)size);
   while (uart_send_complete_flag == 0)
      ;
   uart_send_complete_flag = 0;

   return size;
}
#else
int fputc(int ch, FILE *f)
{
   (void)f;
   R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
   while (uart_send_complete_flag == 0)
      ;
   uart_send_complete_flag = 0;

   return ch;
}
#endif


3.2.5 修改debug_bsp_uart.h

该文件内容为

#ifndef DEBUG_BSP_UART_H_
#define DEBUG_BSP_UART_H_
#include "hal_data.h"
#include "stdio.h"
void Debug_UART9_Init(void);
extern volatile int uart_rx_complete_flag;
extern char rx_data[1024];
#endif


4. 下载测试

把编译好的程序下载到开发板并复位,打开串口助手,在发送框输入

time:20250228235959



注意:

  1. 如果串口助手没有自动添加\r\n,则上面的结尾需要手动加上\r\n,否则程序无法识别该命令。
  2. 程序中未作纠错,请勿输入错误的时间,否则日历将出错。


工程附件

/uploads/03_RTC_1751534486.zip

隐私条款

一、接受条款 使用者(也称"您")在访问或使用本网站及其服务时,即已经表示同意并不加修改地接受本《用户协议》、本网站的《隐私声明》、《法律声明》以及其关或相链接的网页和网站的条件和条款的规定。我们强烈建议:在您阅读和接受本《用户协议》时,也应阅读并接受本《用户协议》中所提到《隐私声明》、《法律声明》及其相关或相链接网页或网站所包含的资料,因为《隐私声明》、《法律声明》及其它相关网页或网站可能包含对您适用的进一步规定。(请注意:点击划有底线的词句即可链接到上述《隐私声明》、《法律声明》及其它相关或相链接的网页和网站。

 

二、使用者的资格要求 在本网站中"使用者"指的是浏览、阅读、使用本网站信息或服务的任何个人或组织。本网站的服务仅适用于根据相关法律的规定具有签订有约束力的合同的个人或组织并仅由其使用。本网站的服务不向18周岁以下的个人使用者提供,也不向临时被本网站中止或取消使用者资格的使用者提供。如果使用者不符合本条规定,请停止使用本网站或本网站的服务。

样品
申请

应用
资源

微信