nRF52832学习记录(七、RTC 实时计数器 )
【摘要】
RTC— Real-time counter
nRF52832 的 RTC— Real-time counter 是实时计数器。 注意不要和单片机上的实时时钟搞混淆。 单片机上的RTC— Real-ti...
RTC— Real-time counter
nRF52832 的 RTC— Real-time counter 是实时计数器。 注意不要和单片机上的实时时钟搞混淆。
单片机上的RTC— Real-time Clock,是提供精确的实时时间或者为电子系统提供精确的时间基准。
nRF52832 的 RTC— Real-time counter 是在低频时钟源 LFCLK 上提供的一个通用的低功耗定时器。
nRF52832 的 RTC的结构如图:
- 使用 RTC 必须 启动 LFCLK时钟;
- nRF52xx 有 RTC0、RTC1、RTC2 三个RTC 模块;
- TICK 事件(滴答事件)常用于低功耗,无滴答RTOS,可在关闭CPU的时候保持RTOS的调度;
- 24位 COUNTER 的分辨率为 30.517us;
- PRESCALER 寄存器在 RTC 停止时可读可写。在启动以后写无效。 PRESCALER 在 START、 CLEAR 和 TRIGOVRFLW 任务发生时都会重新启动。 fRTC [kHz] = 32.768 / (PRESCALER + 1 ) 分频值 被锁在这些任务内部寄存器 PRESC 中
- 溢出事件: 在模块输入端通过 TRIGOVRFLW task 将COUNTER 计数器的值设置为 0xFFFFF0。计数器计数16次, 到 0xFFFFFF,然后溢出到0时就发生 OVRFLW 事件。
Important: The OVRFLW event is disabled by default.
nRF52832 RTC相关寄存器:
EVENT使能和禁止寄存器:
ENENT 和 EVTENSET 类似于学习笔记五里面PPI使用中的 CHEN 和CHENSET
RTC 之COMPARE EVENT 和 TICK EVENT 应用(寄存器版本):
- 配置低速时钟;
- 配置分频值,CC的值;
- 使能中断,使能事件;
#define LFCLK_FREQUENCY (32768UL) /**< LFCLK频率为HZ. */
#define RTC_FREQUENCY (8UL) /**< 所需的RTC工作时钟 RTC_FREQUENCY 为HZ. */
#define COMPARE_COUNTERTIME (3UL) /**<设备比较次数*/
#define COUNTER_PRESCALER ((LFCLK_FREQUENCY/RTC_FREQUENCY) - 1) /* f = LFCLK/(prescaler + 1) */
/* 使用RTC需要使能低速时钟 */
void lfclk_config(void)
{
/* 选择外部32.768k晶振 */
NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
NRF_CLOCK->TASKS_LFCLKSTART = 1;//启动低速时钟任务
while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0){
}
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
}
/*
*/
void rtc_config(void)
{
NVIC_EnableIRQ(RTC0_IRQn); // 使能 RTC中断.
// 设置预分频值,通过想要的频率算预分频值
NRF_RTC0->PRESCALER = COUNTER_PRESCALER;
NRF_RTC0->CC[0] = COMPARE_COUNTERTIME * RTC_FREQUENCY; //设置比较的值.
// 写1使能,Enable TICK event and TICK interrupt:
NRF_RTC0->EVTENSET = RTC_EVTENSET_TICK_Msk;
NRF_RTC0->INTENSET = RTC_INTENSET_TICK_Msk;
// Enable COMPARE0 event and COMPARE0 interrupt:
NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
NRF_RTC0->INTENSET = RTC_INTENSET_COMPARE0_Msk;
}
/*:
触发滴答中断和比较中断
*/
void RTC0_IRQHandler()
{
if ((NRF_RTC0->EVENTS_TICK != 0) &&
((NRF_RTC0->INTENSET & RTC_INTENSET_TICK_Msk) != 0)){
NRF_RTC0->EVENTS_TICK = 0;
LED1_Toggle();
}
if ((NRF_RTC0->EVENTS_COMPARE[0] != 0) &&
((NRF_RTC0->INTENSET & RTC_INTENSET_COMPARE0_Msk) != 0)){
NRF_RTC0->EVENTS_COMPARE[0] = 0;
LED2_Toggle();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
RTC 之COMPARE EVENT 和 TICK EVENT 应用(库函数版本):
#define COMPARE_COUNTERTIME (3UL)
static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
if (int_type == NRF_DRV_RTC_INT_COMPARE0)
{
nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
}
else if (int_type == NRF_DRV_RTC_INT_TICK)
{
nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
}
}
/*
ret_code_t nrf_drv_clock_init(void)
{
ret_code_t err_code = NRF_SUCCESS;
if (m_clock_cb.module_initialized)
{
err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED;
}
else
{
m_clock_cb.p_hf_head = NULL;
m_clock_cb.hfclk_requests = 0;
m_clock_cb.p_lf_head = NULL;
m_clock_cb.lfclk_requests = 0;
err_code = nrfx_clock_init(clock_irq_handler);
#ifdef SOFTDEVICE_PRESENT
if (!nrf_sdh_is_enabled())
#endif
{
nrfx_clock_enable();
}
#if CALIBRATION_SUPPORT
m_clock_cb.cal_state = CAL_STATE_IDLE;
#endif
m_clock_cb.module_initialized = true;
}
NRF_LOG_INFO("Function: %s, error code: %s.",
(uint32_t)__func__,
(uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
return err_code;
}
*/
static void lfclk_config(void)
{
ret_code_t err_code = nrf_drv_clock_init();
APP_ERROR_CHECK(err_code);
nrf_drv_clock_lfclk_request(NULL);
}
static void rtc_config(void)
{
uint32_t err_code;
//初始化RTC实例
nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
config.prescaler = 4095;
/*
nrfx_err_t nrfx_rtc_init(nrfx_rtc_t const * const p_instance,
nrfx_rtc_config_t const * p_config,
nrfx_rtc_handler_t handler)
*/
err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);//回调事件
APP_ERROR_CHECK(err_code);
//void nrfx_rtc_tick_enable(nrfx_rtc_t const * const p_instance, bool enable_irq)
nrf_drv_rtc_tick_enable(&rtc,true);
/*
将比较通道设置为在COMPARE_COUNTERTIME秒后触发中断
nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * const p_instance,
uint32_t channel,
uint32_t val,
bool enable_irq)
*/
err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 8,true);
APP_ERROR_CHECK(err_code);
//启动RTC实例
nrf_drv_rtc_enable(&rtc);
}
...
while(1){
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
RTC 之 OVRFLW EVENT 应用(寄存器版本):
溢出次数是固定的 16次, 所以可以根据修改频率来获取自己需要的时间
//..定义
#define LFCLK_FREQUENCY (32768UL) /**< LFCLK频率为HZ. */
#define RTC_FREQUENCY (8UL) /**< 所需的RTC工作时钟 RTC_FREQUENCY 为HZ. */
#define COUNTER_PRESCALER ((LFCLK_FREQUENCY/RTC_FREQUENCY) - 1) /* f = LFCLK/(prescaler + 1) */
/*低速时钟使能 ...*/
...
/**
功能,配置RTC溢出事件
*/
void rtc_config(void)
{
NVIC_EnableIRQ(RTC0_IRQn);
NRF_RTC0->PRESCALER = COUNTER_PRESCALER;
NRF_RTC0->TASKS_TRIGOVRFLW=1;//触发溢出任务,0xfffff0
// 使能溢出通道和溢出中断
NRF_RTC0->EVTENSET = RTC_EVTENSET_OVRFLW_Msk;
NRF_RTC0->INTENSET = RTC_INTENSET_OVRFLW_Msk;
}
/*
中断
*/
void RTC0_IRQHandler()
{
if ((NRF_RTC0->EVENTS_OVRFLW!= 0) &&
((NRF_RTC0->INTENSET & RTC_INTENSET_OVRFLW_Msk) != 0)){
NRF_RTC0->EVENTS_OVRFLW = 0;//清除事件
NRF_RTC0->TASKS_TRIGOVRFLW=1;//重新触发溢出
LED1_Toggle();//led灯翻转
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
RTC 之 OVRFLW EVENT 应用(库函数版本):
/** 配置溢出中断事件
*/
static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
if (int_type == NRF_DRV_RTC_INT_OVERFLOW){
nrf_gpio_pin_toggle(BSP_LED_0);
nrf_rtc_task_trigger(rtc.p_reg,NRF_RTC_TASK_TRIGGER_OVERFLOW);//重新触发一次溢出事件
}
}
/** RTC配置函数
*/
static void rtc_config(void)
{
uint32_t err_code;
//初始化RTC
nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
config.prescaler = 4095;
err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);
APP_ERROR_CHECK(err_code);
nrf_rtc_task_trigger(rtc.p_reg,NRF_RTC_TASK_TRIGGER_OVERFLOW);//触发溢出事件
//使能溢出通道和溢出中断
nrf_drv_rtc_overflow_enable(&rtc,true);
APP_ERROR_CHECK(err_code);
//使能RTC模块
nrf_drv_rtc_enable(&rtc);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
文章来源: blog.csdn.net,作者:矜辰所致,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_42328389/article/details/120335187
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)