NRF51822——定时器学习笔记

1.概述

nRF51822拥有三个定时器,分别是:TIMER0,TIMER1,TIMER2,如下图:

这里写图片描述

三个定时器有不同的位宽,位宽大小决定了计数器的最大溢出时间。

2. 内部结构分析

这里写图片描述

(1)时钟源选择:

定时器TIMER工作在高时钟源(HFLCK)下,同时包含了一个4位的分频器(PRESCALER),可以对高频时钟源进行分频。时钟源的输入包含两种模式: 1MHZ(PCLK1M)和(PCLK16M)模式,经过分频后得到一个频率f_timer,系统根据f_timer自动选择时钟源,不需要设置。

频率 时钟
f_timer > 1MHz 选择PCLK16M
f_timer <= 1MHz 选择PCLK1M

(2)分频器:

分频器计算如下:

这里写图片描述

HFCLK无论哪种时钟源,均为16MHz,PRESCALER为一个4位分频器,分频值为0——15。当PRESCALER大于9后,分频始终为2的9次方,即最小频率f=16mhz / 2^9。

这里写图片描述

(3)工作模式:

分别为定时器(TIMER)和计数器(COUNTER)。通过寄存器MODE进行设置,MODE = 0—>定时器;MODE= 1 —>计数器。

定时器为递增计数,每一个时钟频率,计数器自增加1;

计数器模式下,每当触发一次寄存器COUNT event,定时器内部的计数器寄存器就会增加1。

(4)比较/捕获功能:

定时器模式下设置比较(COMPARE)/捕获(CAPTURE)寄存器CC[n]的值,可以设置定时时间(Timer value),当定时时间的值和CC[n]寄存器的值相等时,将触发一个比较(COMPARE[n] event)事件。

计数器模式下通过设置一个CAPTURE TASK,当计数器的值和比较/捕获寄存器设定的值(Timer value)相等的时候,将产生一个捕获事件(Capture[n] event)。捕获的值将会存储到寄存器CC[n]中读取。

COMPARE[n] event和Capture[n] event都可以触发中断,若为周期性触发,需要在出发后清除计数值,否则会一直计数,直至溢出。

3. 简单实现例程


//定时器初始化
volatile NRF_TIMER_Type *timer_init(timer_t timer)
{
    volatile NRF_TIMER_Type *p_timer;

    //开启高速16MHZ时钟
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;

    //等待外部振荡器启动
    while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
    {

    }
    switch(timer)
    {
        case TIMER0:
            p_timer = NRF_TIMER0;
            break;
        case TIMER1:
            p_timer = NRF_TIMER1;
            break;
        case TIMER2:
            p_timer = NRF_TIMER2;
            break;
        default:
            p_timer = 0;
            break;
    }
    return p_timer;
}

void nrf_timer_delay_ms(timer_t timer,uint_fast16_t volatile number_of_ms)
{
    volatile NRF_TIMER_Type *p_timer = timer_init(timer);

    if(p_timer == 0)
    {
        while(1);
    }

    p_timer->MODE = TIMER_MODE_MODE_Timer;//定时or计数模式选择
    p_timer->PRESCALER = 9;//分频:16MHZ/9=31250Hz
    p_timer->BITMODE = 16;//16位模式
    p_timer->TASKS_CLEAR = 1;//清除定时器
    p_timer->CC[0] = number_of_ms * 31;//值为:31000
    p_timer->CC[0] += number_of_ms / 4;//值为:250
    p_timer->TASKS_START = 1;//开始定时器
    while(p_timer->EVENTS_COMPARE[0] == 0)//触发后将事件置为1
        {

    }
    p_timer->EVENTS_COMPARE[0] = 0;//清0比较定时器
    p_timer->TASKS_STOP = 1;//停止定时器
}
阅读更多

扫码向博主提问

wwt18811707971

非学,无以致疑;非问,无以广识
去开通我的Chat快问
版权声明:原创文章转载请注明出处。 https://blog.csdn.net/wwt18811707971/article/details/80461289
个人分类: NRF51822专栏
想对作者说点什么? 我来说一句
相关热词

没有更多推荐了,返回首页

关闭
关闭
关闭