nRF51822定时器设置

一、nRF51822的时钟系统

nRF51822有两种时钟源:1、高频时钟HFCLK;2、低频时钟LFCLK。这两种时钟只有当系统处于System ON模式的情况下才可用。

低频时钟源

系统有三种低频时钟源:1、32.768kHz晶体振荡器;2、32.768kHz RC振荡器;3、32.768kHz合成时钟(从HFCLK合成的32.768kHz时钟)



二、定时器/计数器

1、时钟源启动

无论是STM32还是nRF51822,在开启定时器之前,都要开启对应的时钟源,否则,定时器是无法正常工作的。
nRF51822的定时器工作于HFCLK,也就是使用PCLK1M和PCLK16M作为定时器的时钟源。在这里要注意,当定时器设定的分频值使用的定时器频率小于或者等于1MH,且没有其他功能模块请求HFCLK时,系统将自动使用HFCLK的1MHz模式,这样可以节省功耗。
nRF51822定时器设置_第1张图片
根据nRF51822用户手册,HFCLK晶体振荡器通过触发HFCLKSTART任务开启,触发HFCLKSTOP任务关闭。当选择的HFCLK晶体振荡器开启时会产生一个HFCLKSTARTED事件。
上图为nRF51822的时钟源寄存器描述。在打开HFCLK时钟时,为避免以前HFCLK开启可能造成的干扰,在开启HFCLK之前,要先将事件寄存器HFCLKSTARTED(事件寄存器在HFCLK启动时会自动更新为1)清除,然后设置任务寄存器HFCLKSTART使HFCLK开启,最后循环等待HFCLK开启成功。程序如下:
void HFCLK_init(void)
{
	NRF_CLOCK->HFCLKSTARTED=0;
	NRF_CLOCK->HFCLKSTART=0;
	while(NRF_CLOCK->HFCLKSTARTED==0)			//HFCLK晶体振荡器开启时会产生一个HFCLKSTARTED事件
	{
		//Do nothing
	}
}


 
   

2、定时器配置

工作模式:nRF51822的TIMER有两种工作模式:定时器模式(Timer mode)和计数器模式(Counter mode)。
开启与关闭:在所有模式中,TIMER都是通过触发START任务开启,触发STOP任务关闭。
计时时钟:1、在定时器模式下,TIMER内部的计数寄存器(Counter register)在计时频率fTIMER每滴答一次时加1。计时频率通过预分频寄存器PRESCALER来设置。2、在计数器模式下,每当COUNT任务触发一次TIMER内部的计数寄存器(Counter register)加1,也就是计数频率和预分频寄存器在计数器模式下并没有使用。同样,COUNT任务在定时器模式下也没有任何作用。
计数的最大值(溢出时的值):最大计数值可以通过改变在BITMODE寄存器中的TIMER的位宽来实现。BITMODE设定了 Counter寄存器比较/捕获寄存器使用的位数。1、TIMER0:可选择的位宽为8、16、24、32;2、TIMER1和TIMER2:可选择的位宽都为8、16。
比较/捕获寄存器:1、定时器模式:当Counter的值与在比较/捕获寄存器CC[n]中值相等时,对应的比较事件COMPARE[n]将会产生。2、计数器模式:通过设置一个CAPTURE任务,当计数到与比较/捕获寄存器设定的值相等时,CAPTURE[n]任务将会触发“捕获定时器的值(Counter value)到CC[n]寄存器。
nRF51822有TIMER0、TIMER1、TIMER2,这3个TIMER分别带有4个比较/捕获寄存器。比较/捕获寄存器的值不同可以产生不同的定时时间。
定时器配置程序如下所示:
void timer0_init(void)
{
	//设置TIMER0为定时器模式
	NRF_TIMER0->MODE=TIMER_MODE_MODE_Timer;
	//配置预分频寄存器,对时钟源HFCLK进行分频
	NRF_TIMER0->PRESCALER=9;
	//设置计数位宽,决定计数值的最大值
	NRF_TIMER0->BITMODE=TIEMR_BITMODE_BITMODE_16Bit;
}



static void nrf_timer0_delay_ms(uint_fast16_t voloatile number_of_ms)
{
	//每次定时器开始计数前,都要将TIMER内部的计数器清零
	NRF_TIMER0->TASK_CLEAR=1;
	//2^9分频值后,TIMER的计数频率为31250Hz,也就是每32us tick一次。则1ms tick 31.25次,但是CC[0]寄存器不能存储小数,故采用下面方法
	NRF_TIMER0->CC[0]=number_of_ms*31;
	NRF_TIMER0->CC[0]+=number_of_ms/4;
	//启动定时器
	NRF_TIMER0->TASK_START=1;
	
	
	//等待对应的COMPARE[0]事件的发生
	while(NRF_TIMER0->EVENTS_COMPARE[0]==0)
	{
		//COMPARE[0]事件发生之后,跳出循环
	}
	//清除COMPARE[0]事件,为下次定时做准备
	NRF_TIMER0->EVENTS_COMPARE[0]=0;
	
	//关闭定时器
	NRF_TIMER0->TASK_STOP=1;
}

    
定时器设置流程图如上图所示。其中TIMER的内部计数寄存器的值必须清除。因为它会一直计数,直到溢出,然后进入下次循环。当定时器开启时,它会接着定时器停止时的值继续计数,计数器计数就会产生差错。



你可能感兴趣的:(nRF51822)