Prescaler Comparator

该示例通过使用 RTC 的分频比较器实现定时功能。

RTC 时钟源(32kHz)经过预分频之后,普通的比较器定时只能定时 RTC 时钟周期的整数倍时间。(例如预分频后 RTC 时钟周期为 0.1s,则此时 RTC 比较器只支持定时 0.1s 整数倍的时间。) 为了能达到更精细的定时时间,可以采用分频比较器定时。

如果想要定时的时间小于 RTC 时钟周期,需使用 RTC_INT_PRE_COMP 中断进行定时。定时时间为 PreCompValue * (1/32kHz) 。

如果想要定时的时间大于 RTC 时钟周期,需使用 RTC_INT_PRE_COMP3 中断进行定时,并搭配 RTC_COMP3 进行使用。定时时间为 RTC_COMP3_VALUE * (RTC_Clock) + PreCompValue * (1/32kHz) 。

环境需求

该示例支持以下开发套件:

开发套件

Hardware Platforms

Board Name

RTL8752H HDK

RTL8752H EVB

更多信息请参考 快速入门

配置选项

该示例可配置的宏如下:

RTC_PRECOMP3_INT :配置该宏可选择 RTC 分频比较器的模式选择:

  • 1 :表示使用 RTC_INT_PRE_COMP3 中断进行定时,即定时时间超过 RTC 时钟周期。

  • 0 :表示使用 RTC_INT_PRE_COMP 中断进行定时,即定时时间小于 RTC 时钟周期。

编译和下载

该示例的工程路径如下:

Project file: board\evb\io_sample\RTC\Pre_comp3\mdk

Project file: board\evb\io_sample\RTC\Pre_comp3\gcc

请按照以下步骤操作构建并运行该示例:

  1. 打开工程文件。

  2. 按照 快速入门编译 APP Image 给出的步骤构建目标文件。

  3. 编译成功后,在路径 mdk\bingcc\bin 下会生成 app bin app_MP_xxx.bin 文件。

  4. 按照 快速入门MP Tool 给出的步骤将 app bin 烧录至 EVB 内。

  5. 按下 reset 按键,开始运行。

测试验证

  1. 若开启宏 RTC_PRECOMP3_INT,RTC 定时时间为 1.1s。每隔 1.1s 触发 RTC 中断,在中断函数内打印相应信息。

    RTC_Handler
    RTC_INT_PRE_COMP3
    
  2. 若未开启宏 RTC_PRECOMP3_INT,RTC 定时时间为 0.1s。每隔 0.1s 触发 RTC 中断,在中断函数内打印相应信息。

    RTC_Handler
    RTC_INT_PRE_COMP
    

代码介绍

该章节分为以下几个部分:

  1. 源码路径

  2. 初始化函数将在 初始化 章节介绍。

  3. 初始化后的功能实现将在 功能实现 章节介绍。

源码路径

  • 工程路径: sdk\board\evb\io_sample\RTC\Pre_comp3

  • 源码路径: sdk\src\sample\io_sample\RTC\Pre_comp3

该工程的工程文件代码结构如下:

└── Project: rtc_pre_comp3
    └── secure_only_app
        └── include
            ├── app_define.h
            └── rom_uuid.h
        ├── cmsis                    includes CMSIS header files and startup files
            ├── overlay_mgr.c
            ├── system_rtl876x.c
            └── startup_rtl876x.s
        ├── lib                      includes all binary symbol files that user application is built on
            ├── rtl8752h_sdk.lib
            ├── gap_utils.lib
            └── ROM.lib
        ├── peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl876x_rcc.c
            ├── rtl876x_nvic.c
            └── rtl876x_rtc.c
        ├── profile
        └── app                      includes the ble_peripheral user application implementation
            └── main.c

初始化

当 EVB 复位启动时,执行 main 函数。在 rtc_demo 中,包含 RTC 外设的初始化。

int main(void)
{
    extern uint32_t random_seed_value;
    srand(random_seed_value);
    __enable_irq();

    rtc_demo();
    while (1)
    {
        __NOP();
        __NOP();
        __NOP();
        __NOP();
        __NOP();
        __NOP();
    }
}

void rtc_demo(void)
{
    /* Initialize RTC peripheral */
    driver_rtc_init();
}

driver_rtc_init 为 RTC 外设的初始化,包含如下流程:

  1. 复位 RTC 外设。

  2. 若开启宏 RTC_PRECOMP3_INT

    1. 设置 RTC 分频系数为(3200-1),RTC 时钟频率为 10Hz。

    2. 设置分频比较值为 320,即预分频比较器的比较时间为 0.1s。

    3. 设置 RTC_COMP3 比较器的比较值为 10,即比较器的比较时间为 1s,总定时时间为 1.1s。

    4. 配置分频比较器 3 计数中断 RTC_INT_PRE_COMP3

  3. 若未开启宏 RTC_PRECOMP3_INT

    1. 设置 RTC 分频系数为(3200-1),RTC 时钟频率为 10Hz。

    2. 设置分频比较值为 320,即预分频比较器的比较时间为 0.1s。

    3. 设置分频比较器中断 RTC_INT_PRE_COMP

  4. 配置并使能 RTC 的 IRQ 通道,开启 CPU 的 NVIC 中断。

  5. 复位 RTC 计数器,使能 RTC 定时。

void driver_rtc_init(void)
{
    RTC_DeInit();

#if (RTC_PRECOMP3_INT)
    RTC_SetPrescaler(RTC_PRESCALER_VALUE);
    RTC_SetPreCompValue(RTC_PRECOMP_VALUE);
    RTC_SetCompValue(RTC_COMP3, RTC_COMP3_VALUE);

    RTC_INTConfig(RTC_INT_PRE_COMP3, ENABLE);

#else
    RTC_SetPrescaler(RTC_PRESCALER_VALUE);
    RTC_SetPreCompValue(RTC_PRECOMP_VALUE);

    RTC_INTConfig(RTC_INT_PRE_COMP, ENABLE);
#endif
    /* Config RTC interrupt */
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = RTC_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 3;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);

    RTC_NvCmd(ENABLE);
    /* Start RTC */
    RTC_ResetCounter();
    RTC_Cmd(ENABLE);
}

功能实现

RTC 定时时间到,触发 RTC 中断,进入中断处理函数 RTC_Handler

  1. 若开启宏 RTC_PRECOMP3_INT,即定时时间为 1.1s 进入中断。在中断函数内读取 counter 值,重置分频计数器,重新设定比较值,清除中断标志位。

  2. 若未开启宏 RTC_PRECOMP3_INT,即定时时间为 0.1s 进入中断。在中断函数内重置分频计数器,清除中断标志位。

void RTC_Handler(void)
{
    DBG_DIRECT("RTC_Handler");
#if (RTC_PRECOMP3_INT)
    if (RTC_GetINTStatus(RTC_INT_PRE_COMP3) == SET)
    {
        DBG_DIRECT("RTC_INT_PRE_COMP3");
        uint32_t counter  = RTC_GetCounter();
        RTC_ResetPrescalerCounter();
        RTC_SetCompValue(RTC_COMP3, counter + RTC_COMP3_VALUE);
        RTC_ClearINTPendingBit(RTC_INT_PRE_COMP3);
    }
#else
    if (RTC_GetINTStatus(RTC_INT_PRE_COMP) == SET)
    {
        DBG_DIRECT("RTC_INT_PRE_COMP");
        RTC_ResetPrescalerCounter();
        RTC_ClearINTPendingBit(RTC_INT_PRE_COMP);
    }
#endif
}