nRF52832学习记录(七、RTC 实时计数器 )

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 应用(寄存器版本):
  1. 配置低速时钟;
  2. 配置分频值,CC的值;
  3. 使能中断,使能事件;
#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();
    }
}

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){
}

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灯翻转
    }
}

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);

}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

矜辰所致

您们的鼓励是我奋斗的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值