• SynergyS7G2RTC时钟模块的使用


    RTC功能描述

    RTC时钟模块是Synergy芯片的一个时间外设,主要用于日期时间的存储和控制,有别于一般MCU中的Timer,RTC时钟有两种计时模式,日期模式和二进制计时模式,其中日期模式的时间可以表示为“年月日时分秒”格式,日期记录范围为2000年到2099年,可以自动完成闰年调整,对于二进制模式,RTC使用32bit计数器完成秒的计数,可以用于其他历法的日期计算。RTC的使用一般是通过HAL驱动来访问和控制。典型的RTC应用一般是三个方面(1)用于系统计时,(2)产生周期型时间中断来定时做某件事情,(3)注册定时闹铃,在时间到来的时候完成某些工作

    RTC常见的操作包括设置时间、设置定时闹铃、配置周期性中断以及启动或停止操作;

    RTC还有时钟错误纠正功能和CLOCK输出功能,能够对外输出1Hz或64Hz信号。

    RTC的时钟源

    RTC模块可以使用两个主时钟源,片上时钟源LOCO和外部时钟源XCIN,如果使用片上时钟源,可以做到低功耗,但是时钟精度稍差,如果使用外部时钟源,计时精度将得到很大的提高,但是相应的会增加成本。

    RTC的中断类型

    RTC模块可以使用四种不同的中断类型

    1.         在年、月、日、周、小时、分钟或秒的任意组合中产生的定时中断RTC_ALM。

    2.         可以设置每2s, 1s, 1/2s, 1/4s, 1/8s, 1/16s, 1/32s, 1/64s, 1/128s或1/256s产生的周期性中断RTC_PRD。

    3.         当64HZ计数器向秒计数器进位时的或者64Hz计数器发生改变同时R64CNT计数器被读取时会发生中断RTC_CUP。

    4.         当从休眠模式(Software Standby)或者深度休眠模式(Deep Software Standby)恢复时会导致一次RTC_ALM和RTC_PRD。

    RTC结构图

    RTC的结构图如下图所示:

    外部时钟源XCIN或者内部时钟源LOCO经过时RCR4时钟控制寄存器和RADJ钟调整寄存器的共同设置下,产生128Hz的信号进入时间计数器TimerCounter模块的R64CNT计数器,R64CNT计数器是一个8位计数器,但是最高位保留,因此计数的最大值为128,此计数器为只读计数器,每秒产生一次溢出,其溢出信号发送到秒计数器RSECCNT作为秒时钟输入。秒计数器RSECCNT的溢出会作为分计数器RMINCNT的输入,时计数器RHRCNT,日计数器RDAYCNT和月计数器RMONCNT以及年计数器RYRCNT之间也是这样的进位关系。对于周计数器RWKCNT直接使用了时计数器的值完成星期计数。闹铃功能模块(Alarm function)存储了闹铃时间,通过时间比较电路对存储在闹铃中的时间和当前时间做比较,当时间到时会产生RTC_ALM中断。

    时间捕获功能模块(Time capture control unit)可以将时间捕获并存储在RSECCPn(秒捕获)RMINCPn(分捕获)RHRCPn(时捕获)RDAYCPn(日捕获)RMONCPn(月捕获)寄存器中,其中n的值可以取0-2,也就是说可以捕获3个时间。

    SynergyS7G2RTC时钟模块的使用

    在日历模式下,R64CNT后面的计数器存储的数据都是对应时间的BCD码,对于二进制计数模式,BCNT0-BCNT3四个8位计数器组成32位计数器,对R64CNT输出的秒信号进行计数。

    RTC控制寄存器

    RTC有4个控制寄存器RCR1,RCR2,RCR3,RCR4和一个时间调整寄存器RADJ,用于设置工作模式和时间调整,3个控制寄存器RTCCR0,RTCCR1和RTCCR2用于控制时间捕获,具体的控制功能详见芯片用户手册。

    RTC的使用

    通过SSP可以很容易的完成对RTC的设置与使用。在SSP中提供了RTC的驱动程序,主要的API函数有:

    函数名称

    函数功能与调用例子

    .open

    打开时钟,g_rtc0.p_api->open(g_rtc0.p_ctrl, g_rtc0.p_cfg);

    .close

    关闭时钟,g_rtc0.p_api->close(g_rtc0.p_ctrl);

    .calendarTimeSet

    设置日历时间g_rtc0.p_api->calendarTimeSet(g_rtc0.p_ctrl, &start_time_struct_in, true);Set the calendar time.

    .calendarTimeGet

    读日历时间g_rtc0.p_api->calendarTimeGet(g_rtc0.p_ctrl, &current_time_struct_out);

    .calendarAlarmSet

    设置闹铃时间g_rtc0.p_api->calendarAlarmSet(g_rtc0.p_ctrl, &in_alarm_time_struct_in, true);

    .calendarAlarmGet

    对闹铃时间g_rtc0.p_api->calendarAlarmGet(g_rtc0.p_ctrl, &get_alarm_time_struct_out);

    .calendarCounterStart

    日历时间开始计数g_rtc0.p_api->calendarCounterStart(g_rtc0.p_ctrl);

    .calendarCounterStop

    停止日历计数器g_rtc0.p_api->calendarCounterStop(g_rtc0.p_ctrl);

    .irqEnable

    使能闹铃中断g_rtc0.p_api->irqEnable(g_rtc0.p_ctrl, rtc_event);

    .irqDisable

    停止闹铃中断g_rtc0.p_api->irqDisable(g_rtc0.p_ctrl, rtc_event);

    .periodicIrqRateSet

    周期中断设置g_rtc0.p_api->periodicIrqRateSet(g_rtc0.p_ctrl, Rate);

    .infoGet

    获取当前RTC的配置信息g_rtc0.p_api->infoGet(g_rtc0.p_ctrl, &clk_src);

    .versionGet

    获取API版本g_rtc0.p_api->versionGet(&version);

    RTC使用实例:

    1.       打开开发软件e2studio,新建Synergy C工程,选择芯片和用户板;

    2.       在synergy Configurtion中配置HAL/Common线程,加入r_rtc部件驱动,具体位置位于Driver->Timers->RTC Drivr on r_rtc,设置Name属性为g_rtc0,设置Period Interrupt Priority和Carry Interrupt Priority优先级为Priority3;

    3.       检查RTC时钟源是不是LOCO;

    4.       定义中断回调函数Callback的函数名rtc_callback;

    5.       点击Generate Project Content生产代码,检查src/synergy_gen目录中的hal_data.h中有没有回调rtc_callback的声明,在以后代码中要代码实现此函数,用于响应中断事件;

    6.       编写RTC初始化函数,如果只是需要完成一些周期性工作,只需要完成一下几步即可:

    1)         首先调用g_rtc0.p_api->open(g_rtc0.p_ctrl, g_rtc0.p_cfg)打开RTC,

    2)         然后使用g_rtc0.p_api->periodicIrqRateSet(g_rtc0.p_ctrl, PERIODIC_RATE)设置RTC周期中断发生频率,

    3)         接下来调用g_rtc0.p_api->irqEnable(g_rtc0.p_ctrl, IRQ_EVENT)使能中断,

    4)         最后调用g_rtc0.p_api->calendarCounterStart(g_rtc0.p_ctrl)就可以完成RTC初始化了。

    7.       还要编写中断响应函数void rtc_callback(rtc_callback_args_t * p_args),

    void rtc_ callback(rtc_callback_args_t * p_args)
    {
        bsp_leds_t leds;
        R_BSP_LedsGet(&leds);
        static ioport_level_t level_1_sec  = IOPORT_LEVEL_LOW; //LED状态灯,用于1秒闪烁
        static ioport_level_t level_2_sec  = IOPORT_LEVEL_LOW; //LED状态灯,用于2秒闪烁
        static uint8_t seconds = 0;
        if(p_args->event == RTC_EVENT_PERIODIC_IRQ )
    
        {
             if(level_1_sec == IOPORT_LEVEL_LOW)
            {
                 level_1_sec = IOPORT_LEVEL_HIGH;
            }
            else
            {
                level_1_sec = IOPORT_LEVEL_LOW;
            }
            g_ioport.p_api->pinWrite(leds.p_leds[0], level_1_sec);//更新LED1状态
            seconds++;
            if(seconds==2)
            {
                if(level_2_sec == IOPORT_LEVEL_HIGH)
                {
                  level_2_sec = IOPORT_LEVEL_LOW;
                }
                else
                {
                  level_2_sec = IOPORT_LEVEL_HIGH;
                }
                g_ioport.p_api->pinWrite(leds.p_leds[1], level_2_sec); //更新LED2状态
                seconds = 0;
            }
       }
    }

    8.       编译程序,下载并运行,可以看到LED1一秒闪烁一次,LED2两秒闪烁一次.

  • 相关阅读:
    C 语言中 static 的作用
    STM32 标准库
    STM32 HAL库与标准库的区别_浅谈句柄、MSP函数、Callback函数
    asp.net core launchsettings.json
    asp.net core mvc/api部署到iis
    依赖倒置来反转依赖
    ASP.NET Core in2020
    DDD学习一
    asp.net core学习一
    从零开始实现ASP.NET Core MVC的插件式开发
  • 原文地址:https://www.cnblogs.com/jiangzhaowei/p/10071850.html
Copyright © 2020-2023  润新知