nRF51822 学习笔记(三)定时器之应用定时器

一、认识 nRF51822 的时钟系统

阅读 nRF51_Series_Reference_manual 手册可知 nRF51822有两种时钟源: 

1、高频时钟(HFCLK)

其时钟源来自以下两种之一,具体取决于 HFCLKSRC 的配置。

       HFCLK crystal oscillator : 16 or 32 MHz crystal oscillator

       HFCLK RC oscillator : 16 MHz RC oscillator

   HFCLK时钟控制器从HFCL派生出以下时钟给系统,这些时钟仅在系统处于ON模式时可用。

(当系统处于ON模式下时,HFCLK RC振荡器将自动启动,为系统提供所需的时钟)

       HCLK: 16 MHz高频时钟,用于CPU和整个系统。

       PCLK1M: 1 MHz外设时钟。

       PCLK16M: 16 MHz外设时钟。

2、低频时钟(LFCLK)

其时钟源来自以下三种之一

     LFCLK crystal oscillator: 32.768 kHz crystal oscillator
                LFCLK RC oscillator: 32.768 kHz RC oscillator
                LFCLK synthesizer: 32.768 kHz synthesized from HFCLK

    LFCLK时钟控制器为从LFCLK派生的系统提供以下时钟:

    PCLK32KI: 32.768 kHz low frequency clock for peripherals

    当系统从OFF模式转换到ON模式时,LFCLK时钟控制器和所有LFCLK时钟源默认关闭。

关于时钟部分的基本知识,我觉得这篇博客写得很不错 nRF51822 - 时钟设置。

3、外部时钟晶振到内部时钟晶振的转换

如果是要自己设计nRF51822 的外围电路时,就像我最开始只用了一个16M的晶振,没有接外部的32.768K晶振,所以在这个时候使用官方样例的时候,就需要注意对于系统时钟初始化的操作了,往往就需要一个内部RC和外部晶振的转换设置。关于这方面的设置有很多博客说明,我参考的博客是----nRF51822 LRC 内部RC和外部晶振的设置。这里我就不搬运了,就说以下我在具体操作时代码的更改情况。

我使用的样例是ble_app_hrs,在进行将使用外部晶振转换为使用内部的RC振荡器时,我只是对 main.c 中的 ble_stack_init 下对时钟的设置,因为其他博客中提到的修改CLOCK_LFCLKSRC_SRC_Xtal 我并没有在这个样例代码中找到引用它的地方

static void ble_stack_init(void)
{
    uint32_t err_code;
    
    //初始化SoftDevice处理程序模块。
    //SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);//使用外部32.768K晶振
     SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_250MS_CALIBRATION, false);//使用内部的RC振荡器
......
	   
}

二、定时器功能描述

在要开始使用定时器的时,我们必须要先开启对应的时钟源,所以在学习定时器之前需要先了解整个时钟系统。

TIMER 可以在两种模式下工作,定时器模式和计数器模式。在两种模式下,TIMER通过触发 START 任务启动,并通过触发 STOP 任务停止。定时器停止后,定时器可以通过再次触发START任务来恢复定时/计数。当恢复计时/计数时,计时器将从停止之前的值继续。

如果计时器在 STOP 之后不需要被再次启动,则可以使用 SHUTDOWN 任务代替或执行STOP任务。


三、定时器之应用定时器的配置

1、从Keil中下载样例文件

我用的样例文件是ble_app_hrs,样例文件可以直接通过keil MDK 下载下来用。具体方法如下:

首先在keil的菜单栏处选择      加载出了Pack Installer页面之后先在左面选择框选择你的芯片对应的型号,再在右面选择框选择Examples,然后选择你需要的样例,再Copy到本地文件夹下就可以了。

nRF51822 学习笔记(三)定时器之应用定时器_第1张图片

2、应用定时器功能描述

该模块使应用程序能够基于 RTC1 外设创建多个定时器实例。检查用户超时处理程序的超时和调用是在 RTC1中断处理程序 中执行的。列表处理使用软件中断(SWI0)完成。两个中断处理程序都以APP_LOW优先级运行。调用app_timer_start() 或app_timer_stop() 时,定时器操作仅排队,并触发软件中断。实际的定时器启动/停止操作由SWI0中断处理程序执行。由于SWI0中断在APP_LOW中运行,如果调用定时器函数的应用程序代码在APP_LOW或APP_HIGH中运行,则在应用程序处理程序返回之前不会执行定时器操作。例如,在不使用调度程序时从超时处理程序停止计时器时就是这种情况。使用APP_TIMER_INIT()宏的USE_SCHEDULER参数选择是否应使用调度程序。即使未使用调度程序,app_timer.h也将包含app_scheduler.h,因此在编译时,app_scheduler.h必须在其中一个编译器包含路径中可用。

3、应用定时器使用流程及详细参数说明

nRF51822 学习笔记(三)定时器之应用定时器_第2张图片

 使用应用定时器主要的函数就是如上图所示的函数,我们需要配置的参数也就是前三个函数的入口参数。下面将定时每2S 返回一次电量通知的主要代码和定义列举了出来。

其中定时器的模式有两种:一种是定时一次就结束的定时器,第二种是计时器每次时间到期都会重新启动。

static app_timer_id_t                       m_battery_timer_id;       /**< 电池定时器。 */
define APP_TIMER_PRESCALER                  0            /**< RTC1 PRESCALER寄存器的值。 */
#define APP_TIMER_MAX_TIMERS                4          /**< 最大同时创建的计时器数。 */
#define APP_TIMER_OP_QUEUE_SIZE             5          /**< 定时器操作队列的大小。 */
#define BATTERY_LEVEL_MEAS_INTERVAL         APP_TIMER_TICKS(2000, APP_TIMER_PRESCALER)/**< 电池电量测量间隔(滴答)。每2S收到一次电池电量通知 */
 


APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);

    // Create timers
   err_code = app_timer_create(&m_battery_timer_id,APP_TIMER_MODE_REPEATED,battery_level_meas_timeout_handler);
// 启动应用程序计时器
    err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
    APP_ERROR_CHECK(err_code);

4、应用定时器定时时间具体的计算

APP_TIMER_PRESCALER :为时钟分频值,决定了当前时钟采用的时钟频率,当时钟分频数为0时,表示采用的计算定时时间的时钟频率为32.768kHZ。

0       32768

1       16384

3        8192

7       4096

15     2048

31     1024

APP_TIMER_TICKS 为具体定时的毫秒值的宏定义,展开如下

APP_TIMER_TICKS (MS, PRESCALER)      

== ((uint32_t)ROUNDED_DIV((MS) * (uint64_t)APP_TIMER_CLOCK_FREQ, ((PRESCALER) + 1) * 1000))

#define ROUNDED_DIV(A, B)   (A + B / 2) /  B

其中频率和分频值关系为

f RTC [kHz] = 32.768 / (PRESCALER + 1 )

注意:APP_TIMER_TICKS 返回的是 时钟滴答数

所以时钟分频数 = 0 时 

定时1S 即APP_TIMER_TICKS(1000,APP_TIMER_PRESCALER)

计算 返回的时钟滴答数 = ((1000*32768)+1000/2)/1000 = 32768.5

又因为目前时钟分频数 = 0 即目前时钟采用频率为32.768kHz,即一秒钟产生32768次滴答,因此返回的32768滴答数刚好表示定时了1S。

以上都是我自己学习过程中收集的资料以及理解,若有任何不正确的地方,欢迎各位博友留言或者私信指出,我好及时修正错误,共同进步。

参考链接:

nRF51822定时器设置

nRF51822 LRC 内部RC和外部晶振的设置

nRF51822 - 时钟设置

 

你可能感兴趣的:(nRF51822学习笔记)