RT1052 的周期定时器

文章目录

  • 1 PIT 周期中断定时器
  • 2 PIT定时器的使用
  • 3 PIT定时器配置
    • 3.1 PIT 时钟使能。
      • 3.1.1 CLOCK_EnableClock
    • 3.2 初始化 PIT 定时器
      • 3.2.1 PIT_Init
    • 3.3 设置 通道 0 的 加载值
      • 3.3.1 PIT_SetTimerPeriod
    • 3.4 使能 通道 0 的中断
      • 3.4.1 PIT_EnableInterrupts
    • 3.5 开启 PIT 定时器
      • 3.5.1 PIT_StartTimer
    • 3.6开启 PIT 中断并设置优先级
    • 3.7编写中断服务函数
      • 3.7.1 PIT_GetStatusFlags
      • 3.7.2 PIT_ClearStatusFlags
    • 3.8 代码

1 PIT 周期中断定时器

PIT 定时器实际上是一个定时器阵列,RT1052 内部的 PIT 定时器共有 4 个通道,可用于产生中断和触发 DMA。
RT1052 的周期定时器_第1张图片PIT 定时器内部有 4 个计数器(Timer0~Timer3),也就是 4 个通道

  • 这些定时器可以产生中断,或者产生触发条件
  • 其时钟来自外设总线时钟,即 PERCLK_CLK_ROOT,频率为 75M。

PIT功能
1)32 位计数器(CNT),仅支持递减计数方式。
2)支持四个通道。
3)可以级联,实现超长定时(最长可组成 128 位定时器)。
4)支持中断/触发功能。

2 PIT定时器的使用

以 PIT 定时器通道 0 为例

  • 一旦开启 PIT 时钟(MCR[MDIS]=0)
  • 并使能通道 0 的计数(TCTRLx[TEN]=1,x=0~3,下同)
  • 则通道 0 的 CNT 计数器会从 LDVAL0 加载值开始,做递减计数
  • 当 CNT 等于 0 的时候,就产生超时事件,触发中断
  • 然后 CNT 的又会重新加载 LDVAL0 的值,进行下一次递减计数周期,依次循环。

RT1052 的周期定时器_第2张图片

3 PIT定时器配置

3.1 PIT 时钟使能。

使用函数 CLOCK_EnableClock 使能 PIT 时钟。此函数会被 PIT 定时器初始化函数 PIT_Init 调用,所以不需要我们显示的调用。

3.1.1 CLOCK_EnableClock

CLOCK_EnableClock(kCLOCK_Pit)

3.2 初始化 PIT 定时器

使用函数 PIT_Init 初始化 PIT 定时器

3.2.1 PIT_Init

void PIT_Init(PIT_Type *base, const pit_config_t *config)
  • 第一个参数指定使用哪个 PIT,因为 RT1052 只有一个 PIT 定时器,所以这个参数只能为PIT。
  • 第二个参数是指向结构体 pit_config_t 的指针
typedef struct _pit_config
{
	bool enableRunInDebug; //debug 的时候 PIT 是否可以使用
} pit_config_t;

PIT_Init 的一般使用方法如下:

PIT_GetDefaultConfig(&pit_config); //初始化为默认配置
pit_config.enableRunInDebug=true; //调试模式下 PIT 继续运行
PIT_Init(PIT,&pit_config); //初始化 PIT 定时器

3.3 设置 通道 0 的 加载值

使用函数 PIT_SetTimerPeriod 设置通道 0 的加载值,也就是寄存器 LADVAL0 的值。

3.3.1 PIT_SetTimerPeriod

static inline void PIT_SetTimerPeriod(PIT_Type *base, pit_chnl_t channel, uint32_t count)
  • 此函数第一个参数固定为 PIT
  • 第二个参数指定设置哪个通道的:
typedef enum _pit_chnl
{
	kPIT_Chnl_0 = 0U, //PIT 通道 0
	kPIT_Chnl_1, //PIT 通道 1
	kPIT_Chnl_2, //PIT 通道 2
	kPIT_Chnl_3, //PIT 通道 3
} pit_chnl_t;
  • 第三个参数就是要设置的加载值

3.4 使能 通道 0 的中断

使能通道 0 的中断以后,每当设置好的加载值倒计数到 0 就会产生相应的中断。
使用函数 PIT_EnableInterrupts 使能通道 0中断

3.4.1 PIT_EnableInterrupts

static inline void PIT_EnableInterrupts(PIT_Type *base, pit_chnl_t channel, int32_t mask)
  • 第一个参数固定为 PIT
  • 第二个参数是要设置的通道,这里为通道 0,即 kPIT_Chnl_0。
  • 第三个参数是要使能的中断类型
typedef enum _pit_interrupt_enable
{
	kPIT_TimerInterruptEnable = PIT_TCTRL_TIE_MASK,
} pit_interrupt_enable_t;

只 有 一 个 中 断 类 型 kPIT_TimerInterruptEnable。

3.5 开启 PIT 定时器

配置好 PIT 定时器以后需要开启定时器,开启 PIT 定时器的函数为 PIT_StartTimer

3.5.1 PIT_StartTimer

此函数原型如下;

static inline void PIT_StartTimer(PIT_Type *base, pit_chnl_t channel)
  • 第一个参数固定为PIT
  • 第二个产生是要开启哪个通道,这里是通道0,即kPIT_Chnl_0。设置 TCTRL 的 TEN 位为 1。

3.6开启 PIT 中断并设置优先级

在定时器配置完了之后,因为要产生中断,必不可少的要设置 NVIC 相关寄存器
使用如下函数开启 PIT 中断并设置相应的优先级。

RT1052_NVIC_SetPriority(PIT_IRQn,6,0); //抢占优先级 6,子优先级 0
EnableIRQ(PIT_IRQn); //使能 PIT 中断

3.7编写中断服务函数

在中断产生后使用函数 PIT_GetStatusFlags 来获取中断状态,此函数就是获取 TFLG0 的 TIF 位状态,通过 TIF 位状态判断是否是通道 0 的中断。

  • 调用函数 PIT_ClearStatusFlags 来清除相应的中断标志位,就是往 TIF 位写 1。

3.7.1 PIT_GetStatusFlags

中断状态获取函数 PIT_GetStatusFlags 原型如下:

static inline uint32_t PIT_GetStatusFlags(PIT_Type *base, pit_chnl_t channel)
  • 第一个参数是要获取的定时器,这里为 PIT
  • 第二参数就要获取的通道,这里为 kPIT_Chnl_0

此函数其实就是读取寄存器 TFLG 的值,通过这个返回值就可以知道中断是否发生。

3.7.2 PIT_ClearStatusFlags

中断状态(标志位)清除函数 PIT_ClearStatusFlags 原型如下:

static inline void PIT_ClearStatusFlags(PIT_Type *base, pit_chnl_t channel, uint32_t mask)
  • 第一个参数为 PIT
  • 第二参数为要清除的通道,本例程选择 kPIT_Chnl_0
  • 第三个参数是要清除的中断标志位,这里只有 kPIT_TimerFlag 可选择。

3.8 代码

pit_config_t pit_config;

//初始化PIT通道0,PIT时钟源为perclk_clk_root=75MHz.
//ldval: CH0初始值,0~0xFFFFFFFF
//递减计数,当ldval==0时,产生中断.
//定时时间=ldval/PERCLK_CLK_ROOT
void PIT_CH0_Int_Init(u32 ldval)
{
    PIT_GetDefaultConfig(&pit_config);  //初始化为默认配置
    pit_config.enableRunInDebug=true;   //调试模式下PIT继续运行
    PIT_Init(PIT,&pit_config);          //初始化PIT定时器
    
    PIT_SetTimerPeriod(PIT,kPIT_Chnl_0,ldval);//设置倒计时初始值
    PIT_EnableInterrupts(PIT,kPIT_Chnl_0,kPIT_TimerInterruptEnable);//使能中断
    RT1052_NVIC_SetPriority(PIT_IRQn,6,0);	//抢占优先级6,子优先级0
	EnableIRQ(PIT_IRQn);	                //使能PIT中断
    PIT_StartTimer(PIT,kPIT_Chnl_0);        //打开PIT
}

//PIT中断服务函数
void PIT_IRQHandler(void)
{
    //PIT CH0中断
    if((PIT_GetStatusFlags(PIT,kPIT_Chnl_0)&kPIT_TimerFlag)==kPIT_TimerFlag)
    {
        LED1_Toggle;			//LED灯翻转
        PIT_ClearStatusFlags(PIT,kPIT_Chnl_0,kPIT_TimerFlag);//清楚中断标志位
    }
    __DSB();				//数据同步屏蔽指令
}

你可能感兴趣的:(NXP,单片机,嵌入式硬件)