【致敬未来的攻城狮计划】— 连续打卡第二十二天:RA2E1的RTC时钟日历

系列文章目录

1.连续打卡第一天:提前对CPK_RA2E1是瑞萨RA系列开发板的初体验,了解一下

2.开发环境的选择和调试(从零开始,加油)

3.欲速则不达,今天是对RA2E1 基础知识的补充学习。

4.e2 studio 使用教程

5.Keil配置使用(使用 RASC 生成 Keil 工程)

6.Keil配置使用(使用 RASC 生成 Keil 工程)

7.(电脑重装系统)学习RA产品家族选型手册

8.问题解决、学习RA寄存器、用寄存器的方式点亮第一个LED灯。

9.继续学习RA寄存器

10.FSP固件库开发及FSP配置详解。

11.FSP固件库开发点亮第一个灯。

12.FSP固件库开发按键输入检测控制LED灯闪烁

13.FSP固件库开发启动文件详解

14.FSP固件库开发延时函数(时钟详解)

15.FSP固件库外部中断处理编程(外部中断检测按键控制LED闪烁)

16.FSP固件库系统定时器(滴答定时器SysTick)每2秒LED闪烁一次

17.FSP固件库开发GPT — PWM通用定时器 定时2s LED 闪烁

18.FSP固件库开发GPT — PWM输出波形 — LED呼吸灯

19.RA2E1串口通信基础知识

20.RA2E1_UART —— 串口通信例程

21.RA2E1_UART —— 串口控制LED亮灭


文章目录

系列文章目录

文章目录

前言

一、RTC是什么?

二、RTC特性

三、RTC时钟日历(实操)

1.新建工程

2.FSP配置

 3.keil代码编写

总结


前言

        随着时钟的学习,这次学习RTC时钟。(本文章参考野火教程


一、RTC是什么?

        RTC(Real Time Clock)外设,实质是一个掉电后还继续运行的定时器。从定时器的角度来说,相对于GPT外设,要简单很多 ,只有计时和触发中断以及输入捕获的功能。所以RTC外设的特别之处并不在于它的定时功能,而在于它掉电还继续运行的特性。

        以上所说的掉电,是指主电源VDD断开的情况,为了RTC外设掉电继续运行,必须通过VBAT引脚接上纽扣电池给RA6M5的RTC供电。 当主电源VDD有效时,由VDD给RTC外设供电; 而当VDD掉电后,由VBAT给RTC外设供电,继续日历计数器的计时,除此之外RTC的其他功能都无法使用。 若VDD和VBAT都掉电,日历计数器的计时会丢失

        子时钟振荡器或LOCO可以选择作为时间计数器的计数源。RTC使用128Hz的时钟,通过将计数源除以预分频器的值获得: 年、月、日、星期、上午/下午。 (12/24 小时模式)、时、分、秒或32位二进制按1/128秒计数。

二、RTC特性

RTC 特性:

  • 计数模式:日历计数模式和二进制计数模式。

  • 时钟源:子时钟或LOCO。

  • 日历计数模式:年,月,日,星期,小时,分钟,秒计数。

  • 二进制计数模式:32位计二进制计数。

  • 闹钟中断:在日历计数模式下,可以与年,月,日,星期,小时,分钟和秒进行比较。在二进制计数模式下则与32位2进制计数器进行对比。

  • 周期性中断:可以选择2秒,1秒,1/2秒,1/4秒,1/8秒,1/16秒,1/32秒,1/64秒、1/128秒或1/256秒作为中断周期。

  • 进位中断:当从64HZ计数器到二进制计数器的进位时和当改变64Hz计数器和R64同时读取CNT寄存器时进行中断。

  • 输入捕获:当检测到捕获时间输入引脚的电平发生跳变时(上升沿或者下降沿时),可以进行输入捕获。 该输入捕获可以用日历计数或者二进制计数。电平跳变时可以产生中断。与GPT相同的是,该输入捕获也能使用噪声滤波器。

  • 事件关联:周期性输出事件。

  • TrustZone过滤器:可以设置安全属性。

三、RTC时钟日历(实操)

1.新建工程

对于 Keil 开发环境:

        拷贝一份我们之前的 Keil 工程 “RA_UART”, 然后将工程文件夹重命为 “RA_RTC_Date”, 并进入该文件夹里面双击 Keil 工程文件,打开该工程。

【致敬未来的攻城狮计划】— 连续打卡第二十二天:RA2E1的RTC时钟日历_第1张图片

【致敬未来的攻城狮计划】— 连续打卡第二十二天:RA2E1的RTC时钟日历_第2张图片


2.FSP配置

        双击 configuration.xml 打开配置界面:

        然后点开“Pins”->“Peripherals”->“Timers:RTC”->“RTC0”来配置SCI模块: 将“Operation Mode”配置为“Enabled”

【致敬未来的攻城狮计划】— 连续打卡第二十二天:RA2E1的RTC时钟日历_第3张图片

点击配置窗口底部的“Stack”,如图步骤加入RTC模块。 

【致敬未来的攻城狮计划】— 连续打卡第二十二天:RA2E1的RTC时钟日历_第4张图片

属性解释,如下图:

属性

描述

Parameter Cheacking

参数检查,如果设置为Enabled则会检查RTC设置的日历时间是否合法,并通

过年月日自动计算星期。

Set Source Clock in Open

若设置为Enabled,则在函数“R_RTC_Open”中初始化时钟源,若设置为

Disabled,必须调用R_RTC_ClockSourceSet来设置RTC时钟源。

Name

模块名字,可以根据个人需要取名。

Clock Source

设置时钟源,可以选择LOCO和Sub-Clock。

Frequency Comparision Value(LOCO)

使用LOCO作为时钟源时的分频值,取值范围是7-511,默认为255,

则此时输出给日历计数器/二进制计数器的时钟脉冲为

LOCO/(255+1) = 32768/256 = 128Hz

Automatic Adjustment Mode

自动校正模式,用于校正Sub-Clock震荡过快或过慢引起的误差

(例如芯片老化,环境温度过低或过高),默认为Enable。

Automatic Adjustment Period

自动校正的时间,可选择10秒,1分钟或NONE

Adjustment Type(Plus-Minus)

自动校正类型,可以选择None,Addtion或Substraction。选择Addtion则是在

每次自动校正的时候在分频器中加上Error Adjustment Value。

选择Substraction则是在每次自动校正的时候在分频器中减去Error Adjustment Value。

Error Adjustment Value

在触发自动校正时候分频器减去或增加的值。

Callback

RTC中断回调函数的名称,根据读者需求进行设置即可。

Alarm Interrupt Priority

选择闹钟中断的优先级,如果选择Disabled则不使能闹钟中断。

Period Interrupt Priority

选择周期性中断的优先级,如果选择Disabled则不使能周期性中断。

Carry Interrupt Priority

选择进位中断的优先级。

RTCOUT

输出引脚选择,可输出1Hz或64Hz的方波,无法在待机模式下使用。

RTCICn

输入捕获引脚选择。

【致敬未来的攻城狮计划】— 连续打卡第二十二天:RA2E1的RTC时钟日历_第5张图片

        点击刚刚加入的窗口,在左下角的“属性”窗口中配置中断,时钟源,模块名字等属性。由于只有Sub-Clock能使用纽扣电池供电, 故时钟源建议选择Sub-Clock。

【致敬未来的攻城狮计划】— 连续打卡第二十二天:RA2E1的RTC时钟日历_第6张图片


 3.keil代码编写

#include "hal_data.h"
#include "stdio.h"

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER


/**********日期宏定义**********/
#define RTC_YEAR_SET 2008       //年
#define RTC_MON_SET 8           //月
#define RTC_MDAY_SET 8          //日
/*通过蔡勒公式计算星期*/
#define RTC_WDAY_SET (RTC_YEAR_SET-2000 \
                  + ((RTC_YEAR_SET-2000)/4) \
                  - 35 + (26*(RTC_MON_SET+1))/10 \
                  + RTC_MDAY_SET -1 )%7

/**********时间宏定义**********/
#define RTC_HOUR_SET 0          //时
#define RTC_SEC_SET 0           //秒
#define RTC_MIN_SET 0           //分

void RTC_Init(void)
{
   //初始化时设定的时间
   rtc_time_t set_time =
   { .tm_sec = RTC_SEC_SET,  //秒
     .tm_min = RTC_MIN_SET,  //分
     .tm_hour = RTC_HOUR_SET,  //小时
     .tm_mday = RTC_MDAY_SET,  //日(一个月中)
     .tm_wday = RTC_WDAY_SET,   //星期
     .tm_mon = RTC_MON_SET,   //月份
     .tm_year = RTC_YEAR_SET-1900, //年份(如今年是2008,则这里输入2008-1900=108)
   };
   /*打开RTC模块*/
   R_RTC_Open (rtc.p_ctrl, rtc.p_cfg);

   /*时钟源设置,如果在FSP Configuration设置"Set Source Clock in Open"为"enabled",那这一步可以被跳过*/
   R_RTC_ClockSourceSet (rtc.p_ctrl);

   /*若RTC时钟已经使用纽扣电池工作了一段时间,则可以使用这个函数获取当前日历并设置当前时间*/
   //R_RTC_CalendarTimeGet(rtc.p_ctrl,&set_time);

   /*这个函数至少调用一次以启动RTC*/
   R_RTC_CalendarTimeSet (rtc.p_ctrl, &set_time); //设置当前时间

   /*设置周期中断的周期为1秒*/
   R_RTC_PeriodicIrqRateSet (rtc.p_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);
}

void rtc_callback(rtc_callback_args_t *p_args)
{
      static rtc_time_t get_time;
      switch (p_args->event)
      {
         /*若是周期中断,则发送日期给串口并切换LED电平*/
         case RTC_EVENT_PERIODIC_IRQ:
            R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_01, BSP_IO_LEVEL_LOW); //反转LED

            /*获取当前时间*/
            R_RTC_CalendarTimeGet (rtc.p_ctrl, &get_time);

            /*打印当前时间*/
            printf ("\r\n%d-%d-%d-%d:%d:%d\r\n", get_time.tm_year + 1900, get_time.tm_mon, get_time.tm_mday,
                     get_time.tm_hour, get_time.tm_min, get_time.tm_sec);
            break;
         default:
            break;
      }
}

/* 调试串口 UART0 初始化 */
void UART0_Init(void)
{
   fsp_err_t err = FSP_SUCCESS;

   err = R_SCI_UART_Open (&g_uart0_ctrl, &g_uart0_cfg);
   assert(FSP_SUCCESS == err);
}

/* 发送完成标志 */
volatile bool uart_send_complete_flag = false;

/* 串口中断回调 */
void uart0_callback (uart_callback_args_t * p_args)
{
   switch (p_args->event)
   {
      case UART_EVENT_RX_CHAR:
      {
            /* 把串口接收到的数据发送回去 */
            R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&(p_args->data), 1);
            break;
      }
      case UART_EVENT_TX_COMPLETE:
      {
            uart_send_complete_flag = true;
            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_uart4_ctrl, (uint8_t *)pBuffer, (uint32_t)size);
   while(uart_send_complete_flag == false);
   uart_send_complete_flag = false;

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

   return ch;
}
#endif

/*******************************************************************************************************************//**
 * 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)   //相当于主函数  函数最终执行的地方
{
	R_BSP_PinAccessEnable(); //启用对PFS寄存器的访问,因为后面写IO口都用BSP内联函数
	UART0_Init();
	RTC_Init();  //初始化RTC
	printf("硬件初始化完毕\r\n");
	while(1){
	}
	
	
	
	
	
	
	
    /* TODO: add your own code here */

#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

效果:

【致敬未来的攻城狮计划】— 连续打卡第二十二天:RA2E1的RTC时钟日历_第7张图片


总结

            虽然没有板载的RTC试试效果,但是参照了学习,发现难度并不大,于是学习了分享给大家。


风华

你可能感兴趣的:(瑞萨MCU,嵌入式硬件,单片机,stm32,实时音视频,开发语言)