nrf52382之定时器使用

简介

定时器几乎是每个单片机必有的重要外设之一,可用于定时、精确延时、计数等等,在检测、控制领域有广泛应用。

Timer 运行时不占用 CPU 时间,配置好之后,可以与 CPU 并行工作,实现精确的定时和计数,并且可以通过软件控制其是否产生中断,使用起来灵活方便

nRF52832 共有 5 个 32 位的 Timer (Timer0~Timer4),它们都可以工作于定时和计数两种模式,并且 Timer的时钟频率和位宽都可以配置

Timer 时钟源

Timer 使用的时钟源来自 PCLK1M 或 PCLK16M,系统会根据设置的 Timer 时钟频率,fTIMER 自动选择使用哪一个时钟源,即时钟源的设置是无需软件操作的,当我们设置了 Timer时钟频率后,系统会根据时钟频率自动选择时钟源,选择的依据如下:
⚫ 当 fTIMER > 1 MHz 时,定时器模块使用 PCLK16M 作为时钟源。
⚫ 当 fTIMER <= 1 MHz 时,定时器模块使用 PCLK1M 代替 PCLK16M,从而降低功耗

nRF52832 Timer 时钟频率

Timer 的时钟频率 fTIMER 计算公式如下,无论时钟源使用的是 PCLK1M 或 PCLK16M时钟频率计算时都以 16 MHz 为基准

f_TIMER = 16 MHz / (2^PRESCALER)

分频系数可设置的范围是 0~9, 根据上式可计算出时钟频率.

Timer 位宽

nRF52832 的 5 个定时器最大位宽都是 32 位,位宽可以通过 BITMODE 寄存器配置,可配置的位宽有 8 位、 16 位、 24 位和 32 位

Timer 启动和停止

Timer 可以工作于定时或计数模式,无论在哪种模式下, Timer 都是通过触发 START 任务启动,通过触发 STOP 任务寄存器来停止的。 Timer 停止后,触发 START 任务寄存器可以让它再次启动,启动后,定时器将继续从它之前被停止时的值继续计数

Timer0定时器使用代码示例

1.定时器需要引用的头文件

#include "nrf_drv_timer.h"

2.定义Timer0

驱动程序实例的ID对应Timer的ID,如NRF_DRV_TIMER_INSTANCE(0)对应Timer0

const nrfx_timer_t TIMER_LED = NRFX_TIMER_INSTANCE(0);

3.Timer事件回调函数

void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{
    switch (event_type)
    {
        //因为我们配置的是使用CC通道0,所以事件回调
        //函数中判断NRF_TIMER_EVENT_COMPARE0事件
		case NRF_TIMER_EVENT_COMPARE0:
            //翻转指示灯D1状态
            nrf_gpio_pin_toggle(LED_1);
        break;
        default:
            //Do nothing.
            break;
    }
}

4.定时器初始化

void timer_init(void)
{
	uint32_t err_code = NRF_SUCCESS;
	//定时时间200ms
	uint32_t time_ms = 200; 
	//保存定时时间对应的Ticks
    uint32_t time_ticks;
	
	//定义定时器配置结构体,并使用默认配置参数初始化结构体
    nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
	
    //初始化定时器,初始化时会注册timer_led_event_handler事件回调函数
    err_code = nrfx_timer_init(&TIMER_LED, &timer_cfg, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);
	  
	//定时时间(单位ms)转换为ticks
	time_ticks = nrfx_timer_ms_to_ticks(&TIMER_LED, time_ms);
   
    //设置定时器捕获/比较通道及该通道的比较值,使能通道的比较中断
    nrfx_timer_extended_compare(
 &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
}

实验效果

每隔200切换一次LED等的亮灭。

关于nrf52382计数器的使用(以timer0为例)

//定义Timer0的驱动程序实例。驱动程序实例的ID对应Timer的ID,如NRF_DRV_TIMER_INSTANCE(0)对应Timer0

头文件

const nrfx_timer_t TIMER_COUNTER = NRFX_TIMER_INSTANCE(0);

//Timer事件回调函数

void my_timer_event_handler(nrf_timer_event_t event_type, void* p_context){}

定时器计数器配置

//定时器配置计数器初始化
void timer_init(void)
{
	  uint32_t err_code = NRF_SUCCESS;
	
	  //定义定时器配置结构体,并使用默认配置参数初始化结构体
    nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
	
	  //Timer0配置为计数模式
    timer_cfg.mode = NRF_TIMER_MODE_COUNTER;

	
	  //初始化定时器,定时器工作于计数模式时,没有事件,所以无需回调函数,但是nrfx_timer_init函数说明中要求必须提供回调函数,
	  //这里我们提供一个空的回调函数用于注册。
	  //另外,经过实际测试,不提供回调函数,即参数设置为NULL也是可以的
    err_code = nrfx_timer_init(&TIMER_COUNTER, &timer_cfg, my_timer_event_handler);
	  //err_code = nrfx_timer_init(&TIMER_COUNTER, &timer_cfg, NULL);
    APP_ERROR_CHECK(err_code);
}

启动定时器计数器

//启动定时器
nrfx_timer_enable(&TIMER_COUNTER);
int main()
{
    //用于保存读取的计数值
    uint32_t timVal = 0;

	while(1)
	{
		 //定时器计数值加1
		nrfx_timer_increment(&TIMER_COUNTER);	
		//获取计数值
		timVal = nrfx_timer_capture(&TIMER_COUNTER,NRF_TIMER_CC_CHANNEL2);
		printf("conut value:  %d\r\n", timVal);
		
		 //延时1秒
		 nrf_delay_ms(1000);  
	}
}

实验效果

每次主动加1,获取的计数值则加1, 否则计数值不变。
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

路过的小熊~

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值