TIMER控制器

Apollo具有2个独立的定时器。每个定时器均为24bit向下计数。在计数器数值降低为零的时候会产生中断。并且自动重装载计数器数值。

【基本特性】

TIMER控制器的主要特性如下表所示:

  • TIMER控制器时钟源最高可达16MHz,时钟源频率可以进行配置。
  • 每个TIMER通道相互独立,可以分别配置自动装填数值。
  • 24bit向下计数,计数器归零之后自动重装填。
  • 计数器为零是会产生中断请求。

【时钟结构】

TIMER时钟由系统32MHz时钟生成,经过可配置的分频器之后,送往各路TIMER。

分频参数CLK_DIV可以进行配置,CLK_DIV取值范围为0x00-0xFF,当CLK_DIV>0的时候,分频输出频率如下公式所示:

../_images/timer_clk.png

TIMER 的时钟结构如图所示:

../_images/timer_freq.png

【程序设计】

第一步:设置分频参数

分频参数和TIMER通道无关,改变分频参数会改变所有TIMER通道。

所以不在每个通道的参数设置,而是在宏定义中进行设置。在“app_timer.h”中,定义了分频参数以及数据结构。

#define ALL_CHANNEL_TIMER_CLK_DIV     31

输入时钟频率为32MHz,其中“ALL_CHANNEL_TIMER_CLK_DIV”即CLK_DIV分频数值,取值范围是0x00-0xFF。参数取值与分频数值如下表所示:

ALL_CHANNEL_TIMER_CLK_DIV 分频
0 1/2
0x01-0xFF 1/(1+ ALL_CHANNEL_TIMER_CLK_DIV)

第二步:实例化TIMER对象

pp_timer_inst_t timer0 = TIMER_INSTANCE(0);
pp_timer_inst_t timer1 = TIMER_INSTANCE(1);

如果使用TIMER外设,必须首先声明TIMER实例,然后才可以对实例进行操作。

其中“TIMER_INSTANCE”宏定义可以进行TIMER实例的声明,其中的参数为TIMER控制器序号,数值为0-1。

如需同时使用多个TIMER通道,则需要同时声明多个实例。上述代码声明了2个TIMER实例,可以同时使用2个定时器。

第三步:设置TIMER实例参数,并初始化

timer0.param.auto_reload_value = (500*1000L);
timer0.param.callback = app_timer_interrupt_callback0;
timer0.param.callback_param = 0;
app_timer_init (&timer0.inst);

TIMER实例的参数在param成员中,共有3个参数,参数含义如下表所示:

参数 含义
auto_reload_value 自动重装填数值。也就是每次进入中断的间隔时间。
callback 中断回调函数。
callback_param 中断回调函数的参数。

设置完毕参数之后,采用app_timer_init函数来进行初始化。

初始化操作会配置定时器的一些寄存器,以及中断配置。

但是不会启动定时器。若要启动定时器,需要进行第四步的操作。

第四步:开启或关闭定时器:

app_timer_start(&timer0.inst);
app_timer_stop (&timer0.inst);
函数 含义
app_timer_start 启动定时器。
app_timer_stop 关闭定时器。

【实例配置与效果】

在下述测试中,在定时器中断回调函数中进行反转GPIO的操作,同时使用逻辑分析仪观察GPIO的波形。参数配置以及波形如下图所示:

配置1:

参数 取值
ALL_CHANNEL_TIMER_CLK_DIV 31
auto_reload_value 500*1000
波形  
../_images/timer_example1.png  

配置2:

参数 取值
ALL_CHANNEL_TIMER_CLK_DIV 31
auto_reload_value 3000*1000
波形  
../_images/timer_example2.png  

配置3:

参数 取值
ALL_CHANNEL_TIMER_CLK_DIV 15
auto_reload_value 400
波形  
../_images/timer_example3.png  

配置4:

参数 取值
ALL_CHANNEL_TIMER_CLK_DIV 15
auto_reload_value 4000
波形  
../_images/timer_example4.png