跳转至

通用定时器(TIMER)


1、简介

  • TIMER(通用定时器)是一个基于可配置分频器和多种计数方式32位递减计数器,在计数值达到0时触发一个定时事件,常用于在指定的时间间隔内反复触发指定窗口的定时器事件,可作为周期性中断发生器、事件计数器使用。
  • CI13XX支持4个专用TIMER:TIMER0~TIMER3,支持TIMER级联,PWM4和PWM5也可以当作TIMER功能使用。

2、特性

  • 支持三种计数模式,通过API(timer_init、timer_set_mode)进行配置:单周期计数模式、自动重装载计数模式、自由运行计数模式;
  • 单周期计数模式:定时器仅计数一个计数周期;
  • 自动重装载计数模式:计数器在每个计数结束时重新初始化;
  • 自由运行计数模式:计数值在每次计数结束时从0xFFFFFFFF循环到0x00000000;
  • 支持计数时钟分频,支持1、2、4、16分频,通过API(timer_init)进行配置;
  • 支持32位递减计数器,可读取计数器的实时值,通过API(timer_get_count)进行读取;
  • 支持级联模式配置,通过API(timer_cascade_set)进行配置;
  • 支持计数完成上报中断,中断清除方式具体参见API(timer_clear_irq);

3、API列表

函数名 描述
timer_init 初始化TIMER设备
timer_start 启动TIMER设备
timer_stop 停止TIMER设备
timer_set_mode 设置TIMER设备计数模式
timer_event_start TIMER设备触发事件计数
timer_set_count TIMER设置计时周期
timer_get_count TIMER设备获取计数值
timer_cascade_set TIMER设备设置级联模式
timer_clear_irq TIMER中断清除

4、TIMER相关说明

TIMER名 中断名 中断服务函数 描述
TIMER0 TIMER0_IRQn TIMER0_IRQHandler
TIMER1 TIMER1_IRQn TIMER1_IRQHandler
TIMER2 TIMER2_IRQn TIMER2_IRQHandler
TIMER3 TIMER3_IRQn TIMER3_IRQHandler
AON_TIMER0 AON_TIM_INT0_IRQn AON_TIM_INT0_IRQHandler HAL_PWM4_BASE 可当做 AON_TIMER0
AON_TIMER1 AON_TIM_INT1_IRQn AON_TIM_INT0_IRQHandler HAL_PWM5_BASE 可当做 AON_TIMER1


5、示例

TIMER中断服务函数是wake类型,可以在其他任意位置定义该函数:

#include "ci130x_timer.h"
#include "ci_log.h"

//TIMER0中断服务函数定义
void TIMER0_IRQHandler(void)
{
    mprintf("timer0 irq\n");
    timer_clear_irq(TIMER0);
}

//TIMER1中断服务函数参考TIMER0
//TIMER2中断服务函数参考TIMER0
//TIMER3中断服务函数参考TIMER0
//AON_TIMER0中断服务函数参考TIMER0
//AON_TIMER1中断服务函数参考TIMER0

注意

配置中断宽度为 timer_iqr_width_f 时,如果使能了中断,必须调用接口 timer_clear_irq 清除中断。其他中断宽度,硬件会自清中断。

以下代码配置并启动TIMER0,传参1时,表示1S来一次定时器中断:

#include "ci130x_time.h"
#include "ci130x_timer.h"
#include "ci130x_core_eclic.h"

void timer_s(uint32_t s)
{
    /*TIMER0控制器时钟配置*/
    scu_set_device_gate(HAL_TIMER0_BASE,ENABLE);
    /*使能TIMER0中断*/
    eclic_irq_enable(TIMER0_IRQn);
    /*TIMER0初始化*/
    timer_init_t init;
    init.mode = timer_count_mode_auto;      //自动重新计数模式
    init.div = timer_clk_div_0;             //不分频
    init.width = timer_iqr_width_f;         //该中断宽度,需调用timer_clear_irq清除中断
    init.count = get_apb_clk() * s;         //计时多少s的count值
    timer_init(TIMER0,init);
    /*TIMER0启动计时*/
    timer_start(TIMER0);
}

以下代码配置并启动TIMER0,传参1时,表示1ms来一次定时器中断:

#include "ci130x_time.h"
#include "ci130x_timer.h"
#include "ci130x_core_eclic.h"

void timer_ms(uint32_t ms)
{
    /*TIMER0控制器时钟配置*/
    scu_set_device_gate(HAL_TIMER0_BASE,ENABLE);
    /*使能TIMER0中断*/
    eclic_irq_enable(TIMER0_IRQn);
    /*TIMER0初始化*/
    timer_init_t init;
    init.mode = timer_count_mode_auto;          //自动重新计数模式
    init.div = timer_clk_div_0;                 //不分频
    init.width = timer_iqr_width_f;             //该中断宽度,需调用timer_clear_irq清除中断
    init.count = (get_apb_clk() / 1000) * ms;   //计时多少ms的count值
    timer_init(TIMER0,init);
    /*TIMER0启动计时*/
    timer_start(TIMER0);
}

以下代码配置并启动TIMER0,传参1时,表示1us来一次定时器中断:

#include "ci130x_time.h"
#include "ci130x_timer.h"
#include "ci130x_core_eclic.h"

void timer_us(uint32_t us)
{
    /*TIMER0控制器时钟配置*/
    scu_set_device_gate(HAL_TIMER0_BASE,ENABLE);
    /*使能TIMER0中断*/
    eclic_irq_enable(TIMER0_IRQn);
    /*TIMER0初始化*/
    timer_init_t init;
    init.mode = timer_count_mode_auto;            //自动重新计数模式
    init.div = timer_clk_div_0;                   //不分频
    init.width = timer_iqr_width_f;               //该中断宽度,需调用timer_clear_irq清除中断
    init.count = (get_apb_clk() / 1000000) * us;  //计时多少us的count值
    timer_init(TIMER0,init);
    /*TIMER0启动计时*/
    timer_start(TIMER0);
}

警告

CI13XX系列芯片内置32位计数器,计数范围:0x0 - 0xFFFFFFFF;如果需要更长时间的定时设置,需要对定时器进行分频操作,或使用级联模式。


6、常见问题

  • TIMER定时范围(TIMER模块基础时钟CLK_S = 120000000Hz)

分频系数:DIV(取值范围:1,2,4,16)

计数时钟:CLK = CLK_S / DIV 单位:Hz

最小定时:MIN = 1s / CLK 单位:S

最大定时:MAX = 0xFFFFFFFF * MIN 单位:S

以上做法,最大定时9分钟左右,若需要更长时间定时,请使用定时器级联模式。以下对级联模式进行描述:

TODO:

基础定时器 级联定时器
TIMER0 TIMER1\2\3
TIMER1 TIMER2\3
TIMER2 TIMER3
AON_TIMER0 AON_TIMER1

举个例子: 我们现在将TIMER0作为基础定时器,将时钟分频系数配置为16(这里追求定时最大化),TIMER1、TIMER2、TIMER3都配置为级联模式,且TIMER1、TIMER2、TIMER3的计数值都配置为最大值(0xFFFFFFFF),那么每一个TIMER定时是多久呢?

定时器 定时时间
TIMER0 13分钟左右
TIMER1 0xFFFFFFFF * 13分钟左右
TIMER2 0xFFFFFFFF * 0xFFFFFFFF * 13分钟左右
TIMER3 0xFFFFFFFF * 0xFFFFFFFF * 0xFFFFFFFF * 13分钟左右
AON_TIMER0 13分钟左右
AON_TIMER1 0xFFFFFFFF * 13分钟左右

7、API 参考