0%

【nRF52832】学习笔记 --> TIMER-Timer/Counter (定时器/计数器)

😊 转载请全文转载,并标明文章出处

环境介绍

  • 操作系统: Window10 企业版
  • IDE开发环境: ARM_MDK5 (Keil5)
  • SDK版本: SDK_17.0.0
  • 硬件开发板: 官方开发板 PCA10040

TIMER-Timer/Counter (定时器/计数器)

1. 概述介绍

  定时器有两种模式:定时器计数器。定时器和计数器内部结构框图如下:

timer_counter

  不管使用什么 MCU 处理器,都必定含有定时器和计数器,针对Nordic芯片,nRF52xx系列的Timer定时器页十分强大,其内部含有5个定时器,Timer0、Timer1、Timer2、Timer3、Timer4。如果使用蓝牙的话,Timer0是被 BLE 占有的,所以只能使用后边4个定时器,Timer1、Timer2、Timer3、Timer4。

Timer

2. Timer / Counter 原理分析

2.1 Timer / Counter 定时器和计数器的区别
  • 定时器和计数器实际都是通过计数器来计数。
  • 定时器是对周期不变的脉冲计数 (一般来自系统时钟),由计数的个数和脉冲的周期即可计算出时间。同时,通过一个给定的预期值 (即比较值),当计数值达到预期值时产生中断,这实现了定时,应用程序通过设置不同的预期值实现不同时间的定时。
  • 计数器时对某一事件进行计数,此事件没发生一次,计数值加/减1,事件的产生可能时没有规律的,计数器的用途是对事件发生的次数进行计数,由计数值来反映事件产生的次数。
2.2 Timer 时钟源

  Timer时钟源主要来源是 PCLK1M 或 PCLK16M,系统会自动根据Timer时钟设置的频率 f 自动选择使用哪一种时钟源,时钟源的设置是无需软件操作的,当我们设置好Timer时钟频率后,系统会根据时钟频率自动选择时钟源。

  • f TIMER = 16MHz / 2PRESCALER

  • f TIMER > 1MHz,定时器使用 PCLK16M 作为时钟源。

  • f TIMER <= 1MHz,定时器使用 PCLK1M 代替 PCLK16M,降低功耗。

2.3 Timer 时钟频率

  Timer 的时钟频率 f TIMER 计算公式: f TIMER = 16MHz / 2PRESCALER,无论时钟源使用的是 PCLK1M 或 PCLK16M ,时钟频率计算都以 16MHz 为基准。

分频系数 时钟频率 系统时钟源
0 16MHz PCLK16M
1 8MHz PCLK16M
2 4MHz PCLK16M
3 2MHz PCLK16M
4 1MHz PCLK1M
5 500KHz PCLK1M
6 250KHz PCLK1M
7 125KHz PCLK1M
8 62.5KHz PCLK1M
9 31.25KHz PCLK1M
2.4 Timer 位宽

  nRF52832 5个定时器最大位宽都是 32 Bit, BITMODE 寄存器可以设置定时器的位宽。

Bit Width ID Bit Width Select Description
16Bit 0 16 bit timer bit width
8Bit 1 8 bit timer bit width
24Bit 2 24 bit timer bit width
32Bit 3 32 bit timer bit width

定时器频率和定时器位宽建议设置 16MHz 和 32Bit (本人比较懒不想去算了),也可以根据自己的定时时间及频率来选择合适的值。

2.5 Timer 捕获

  Timer 中的每一个CC[n]寄存器都对应一个捕获任务 TASKS_CAPTURE,每次出发任务寄存器 CAPTURE[n],捕获值会被存储到对应的CC[n]寄存器。

2.6 Timer 溢出和清零

  Timer 计数寄存器的值增加到最大值时,计数寄存器溢出,计数寄存器的数值会清零并自动从零开始计数。出发任务寄存器 CLEAR,计数寄存器的值也会被清零。

2.7 Timer 比较

  Timer 中每一个CC[n]寄存器都对应一个比较事件 COMPARE,计数值增加到和CC[n]寄存器设置的数值一样时,会产生比较事件 COMPARE[n]。

2.8 Timer 任务延迟和任务优先级
  • 任务延迟:Timer 启动后,CLEAR 任务、COUNT任务、STOP任务会在PCLK16M 的一个时钟周期内生效。
  • 任务优先级:START 任务和 STOP 任务在同一个时钟周期内同时触发时,STOP 任务优先执行。

3. Timer/Counter (定时器/计数器) 代码实现

3.1 Timer.c 配置
/*
* timer.c
*
* Created on: 2020-7-17
* Author: wuliZhao_ch
* Description: library function versions implement timers
*/

#include "timer.h"

#define TIMER0 0

#define TIMER_MS
//#define TIMER_US

const nrf_drv_timer_t TIMER_TASK = NRF_DRV_TIMER_INSTANCE(0); /* Create Timer0 Instance */



/**
* @brief Handler for timer events.
*/
void timer_task_event_handler(nrf_timer_event_t event_type, void* p_context)
{
switch (event_type)
{
case NRF_TIMER_EVENT_COMPARE0: /* CC[0] Compare event match */
LED_Toggle(LED2);
break;
// case NRF_TIMER_EVENT_COMPARE1: /* CC[1] Compare event match */
// break;
// case NRF_TIMER_EVENT_COMPARE2: /* CC[2] Compare event match */
// break;
// case NRF_TIMER_EVENT_COMPARE3: /* CC[3] Compare event match */
// break;
// case NRF_TIMER_EVENT_COMPARE4: /* CC[4] Compare event match */
// break;
// case NRF_TIMER_EVENT_COMPARE5: /* CC[5] Compare event match */
// break;

default:
// Do nothing.
break;
}
}


/**
* @brief HardWare Timer Initialization.
* @param Times : timing time
*/
void hardWare_timer_init(uint32_t times)
{
uint32_t time_ticks;
uint32_t err_code = NRF_SUCCESS;

#if defined (TIMER_MS)

nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;

err_code = nrf_drv_timer_init(&TIMER_TASK, &timer_cfg, timer_task_event_handler);
APP_ERROR_CHECK(err_code);

time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_TASK, times);

nrf_drv_timer_extended_compare(&TIMER_TASK, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

nrf_drv_timer_enable(&TIMER_TASK);
#endif

#if defined (TIMER_US)

nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;

err_code = nrf_drv_timer_init(&TIMER_TASK, &timer_cfg, timer_task_event_handler);
APP_ERROR_CHECK(err_code);

time_ticks = nrf_drv_timer_us_to_ticks(&TIMER_TASK, Times);

nrf_drv_timer_extended_compare(&TIMER_TASK, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

nrf_drv_timer_enable(&TIMER_TASK);

#endif
}
3.2 Timer.h 配置
/*
* timer.h
*
* Created on: 2020-7-17
* Author: wuliZhao_ch
* Description: library function versions implement timers
*/

#ifndef TIMER_H__
#define TIMER_H__

#include <stdbool.h>
#include <stdint.h>
#include "nrf_drv_timer.h"
#include "app_error.h"
#include "nrf_gpio.h"

#include "led.h"

void timer_task_event_handler(nrf_timer_event_t event_type, void* p_context);
void hardWare_timer_init(uint32_t times);




#endif /* TIMER_H__ */
3.3 Main.c 配置
/**
* @brief Function for application main entry.
*/
int main(void)
{

nrf_drv_clock_hfclk_request(NULL);
if(nrf_drv_clock_hfclk_is_running())
{
NRF_LOG_INFO("hfclk_clock_init_succeed!!!\r\n");
}

LED_Init(); /* Initialize LED */
hardWare_timer_init(1000); /* HardWare Timer Initialization */


while (true)
{

}
}
/** @} */