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
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译 APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下 reset 按键,开始运行。
测试验证
若开启宏
RTC_PRECOMP3_INT
,RTC 定时时间为 1.1s。每隔 1.1s 触发 RTC 中断,在中断函数内打印相应信息。RTC_Handler RTC_INT_PRE_COMP3
若未开启宏
RTC_PRECOMP3_INT
,RTC 定时时间为 0.1s。每隔 0.1s 触发 RTC 中断,在中断函数内打印相应信息。RTC_Handler RTC_INT_PRE_COMP
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
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 外设的初始化,包含如下流程:
复位 RTC 外设。
若开启宏
RTC_PRECOMP3_INT
:
设置 RTC 分频系数为(3200-1),RTC 时钟频率为 10Hz。
设置分频比较值为 320,即预分频比较器的比较时间为 0.1s。
设置
RTC_COMP3
比较器的比较值为 10,即比较器的比较时间为 1s,总定时时间为 1.1s。配置分频比较器 3 计数中断
RTC_INT_PRE_COMP3
。若未开启宏
RTC_PRECOMP3_INT
:
设置 RTC 分频系数为(3200-1),RTC 时钟频率为 10Hz。
设置分频比较值为 320,即预分频比较器的比较时间为 0.1s。
设置分频比较器中断
RTC_INT_PRE_COMP
。配置并使能 RTC 的 IRQ 通道,开启 CPU 的 NVIC 中断。
复位 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
。
若开启宏
RTC_PRECOMP3_INT
,即定时时间为 1.1s 进入中断。在中断函数内读取 counter 值,重置分频计数器,重新设定比较值,清除中断标志位。若未开启宏
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 }