RT1064学习笔记

您所在的位置:网站首页 定时器产生中断的频率是什么 RT1064学习笔记

RT1064学习笔记

2024-07-14 10:26| 来源: 网络整理| 查看: 265

RT1064 周期中断定时器简介

PIT模块是一组计时器,可用于引发中断和触发DMA通道。 PIT定时器框图如下图所示:

在这里插入图片描述 PIT定时器内部有4个计数器(Timer0~Timer3) PIT定时器功能包括:

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

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

PIT寄存器简介 PIT Module Control Register (MCR)

PIT控制寄存器 在这里插入图片描述 该寄存器用于设置 PIT 定时器的运行(开/关),只有最低 2 位有效

MDIS 位,用于控制PIT 的时钟使能,0,使能;1,禁止。

FRZ 位,用于控制 PIT 在 Debug 模式下是否继续运行,0,Debug 模式继续运行;1,Debug 模式停止运行。

Timer Load Value Register (LDVAL0 - LDVAL3)

通道加载值寄存器 在这里插入图片描述 该寄存器确定 PIT 定时器具体某个通道的加载值,4 个通道,总共有 4 个寄存器。每个通道的初始计数值就是从由该寄存器决定,然后进行递减计数,计数到 0 时产生中断/触发,然后自动重载 LDVALx 的值,然后开启下一次递减计数。

所以,在时钟频率确定的前提下(PIT 的时钟源来自 PERCLK_CLK_ROOT),中断周期由该寄存器确定,计算公式为: T o u t = L D V A L x P E R C L K _ C L K _ R O O T Tout=\frac{LDVALx}{PERCLK\_CLK\_ROOT} Tout=PERCLK_CLK_ROOTLDVALx​ 其中PERCLK_CLK_ROOT 的频率一般为 75Mhz LDVALx的取值为1~4,294,967,295

Timer Control Register (TCTRL0 - TCTRL3)

通道控制寄存器 在这里插入图片描述 该寄存器用于设置 PIT 定时器的某个通道,4 个通道,总共有 4 个寄存器。 CHN 位[2]:用于设置是否使用级联模式。0,不使用;1,使用。如果使用级联模式(通道 0不能级联),该通道的计数,只有在前一个通道计数完成后,才减 1。 2 个通道级联就可以组成一个 64 位的计数器,按 75M 的计数时钟算,可以计数 7799 年才会溢出!!。虽然可以 4 路级联,组成 128 位定时器,但是延时时间实在是太久了,实际上一般用不到。

TIE 位[1]:用于设置是否使能中断功能。0,不使能;1,使能。如果使能,则在定时器通道计数到 0 的时候,将会产生中断。

TEN 位[2]:用于设置是否使能该通道。0,不使能;1,使能。本章我们需要用到通道 0,所以通道 0 的 TEN 位需要设置为 1。

Timer Flag Register (TFLG0 - TFLG3)

通道标志寄存器

在这里插入图片描述 该寄存器只有最低位(TIF)有效,用于表示对应通道是否产生了超时事件(计数到 0),该位为写 1 清零。同样的,4 个通道,有 4 个 TFLG 寄存器。

PIT库函数

PIT 相关的库函数在 fsl_pit.c 和 fsl_pit.h

1.PIT时钟使能

使用函数 CLOCK_EnableClock 使能 PIT 时钟,使用方法如下:

CLOCK_EnableClock(kCLOCK_Pit)

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

2.初始化PIT定时器

用函数 PIT_Init 初始化 PIT 定时器,此函数原型如下:

void PIT_Init(PIT_Type *base, const pit_config_t *config)

第一个参数PIT_Type *base:PIT,在MIMXRT1064.h中21006中30794 第二个参数pit_config_t *config:

typedef struct _pit_config { bool enableRunInDebug; /*!< true: Timers run in debug mode; false: Timers stop in debug mode ,debug 的时候 PIT 是否可以使用*/ } pit_config_t;

可以看到这个结构体很简单只有一个成员变量,用来标记debug的时候PIT是否可以使用。 函数 PIT_Init 的一般使用方法如下:

PIT_GetDefaultConfig(&pit_config); //初始化为默认配置 pit_config.enableRunInDebug=true; //调试模式下 PIT 继续运行 PIT_Init(PIT,&pit_config); //初始化 PIT 定时器 3.设置通道0的加载值

使用函数 PIT_SetTimerPeriod 设置通道 0 的加载值,也就是寄存器 LADVAL0 的值,此函数原型如下:

static inline void PIT_SetTimerPeriod(PIT_Type *base, pit_chnl_t channel, uint32_t count) { base->CHANNEL[channel].LDVAL = count; }

第一个参数PIT_Type *base:PIT,在MIMXRT1064.h中21006中30794 第二个参数 pit_chnl_t channel:可设置的通道如下

typedef enum _pit_chnl { kPIT_Chnl_0 = 0U, /*!< PIT channel number 0*/ kPIT_Chnl_1, /*!< PIT channel number 1 */ kPIT_Chnl_2, /*!< PIT channel number 2 */ kPIT_Chnl_3, /*!< PIT channel number 3 */ } pit_chnl_t;

第三个参数 uint32_t count:要设置的加载值,此加载值就确定了 PIT 定时器的定时时间。

4.使能通道0的中断

使能通道 0 的中断以后,每当设置好的加载值倒计数到 0 就会产生相应的中断,这样就实现了定时器功能,我们可以在中断中做具体的处理。 使用函数 PIT_EnableInterrupts 使能通道 0中断,此函数原型如下:

static inline void PIT_EnableInterrupts(PIT_Type *base, pit_chnl_t channel, uint32_t mask) { base->CHANNEL[channel].TCTRL |= mask; }

第一个参数PIT_Type *base:PIT,在MIMXRT1064.h中21006中30794 第二个参数 pit_chnl_t channel:可设置的通道如下

typedef enum _pit_chnl { kPIT_Chnl_0 = 0U, /*!< PIT channel number 0*/ kPIT_Chnl_1, /*!< PIT channel number 1 */ kPIT_Chnl_2, /*!< PIT channel number 2 */ kPIT_Chnl_3, /*!< PIT channel number 3 */ } pit_chnl_t;

第三个参数 uint32_t mask:要使能的中断类型,可选的中断类型如下:

/*! @brief List of PIT interrupts */ typedef enum _pit_interrupt_enable { kPIT_TimerInterruptEnable = PIT_TCTRL_TIE_MASK, /*!< Timer interrupt enable*/ } pit_interrupt_enable_t;

只有一个中断类型kPIT_TimerInterruptEnable,所以只能选它了[sad]

5.开启PIT定时器

配置好 PIT 定时器以后需要开启定时器,否则 PIT 定时器不会工作,开启 PIT 定时器的函数为 PIT_StartTimer,此函数原型如下;

static inline void PIT_StartTimer(PIT_Type *base, pit_chnl_t channel) { base->CHANNEL[channel].TCTRL |= PIT_TCTRL_TEN_MASK; }

第一个参数PIT_Type *base:PIT,在MIMXRT1064.h中21006中30794 第二个参数 pit_chnl_t channel:可设置的通道如下

typedef enum _pit_chnl { kPIT_Chnl_0 = 0U, /*!< PIT channel number 0*/ kPIT_Chnl_1, /*!< PIT channel number 1 */ kPIT_Chnl_2, /*!< PIT channel number 2 */ kPIT_Chnl_3, /*!< PIT channel number 3 */ } pit_chnl_t; 6.开启PIT中断并设置优先级

在定时器配置完了之后,因为要产生中断,必不可少的要设置 NVIC 相关寄存器,以使能GPT1 的中断。

NVIC_SetPriority(PIT_IRQn,10);

因为是基于逐飞库写的,所以只需要指定中断优先级,最后会开启中断

7.编写中断服务函数

编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。

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

如果是通道 0 中断的话就执行相关操作,最后调用函数 PIT_ClearStatusFlags 来清除相应的中断标志位,就是往 TIF 位写 1。

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

static inline uint32_t PIT_GetStatusFlags(PIT_Type *base, pit_chnl_t channel) { return (base->CHANNEL[channel].TFLG & PIT_TFLG_TIF_MASK); }

第一个参数PIT_Type *base:PIT,在MIMXRT1064.h中21006中30794 第二个参数 pit_chnl_t channel:可设置的通道如下

typedef enum _pit_chnl { kPIT_Chnl_0 = 0U, /*!< PIT channel number 0*/ kPIT_Chnl_1, /*!< PIT channel number 1 */ kPIT_Chnl_2, /*!< PIT channel number 2 */ kPIT_Chnl_3, /*!< PIT channel number 3 */ } pit_chnl_t;

此函数其实就是读取寄存器 TFLG 的值,然后做简单的处理并将处理后的值返回给调用者,通过这个返回值就可以知道中断是否发生。

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

static inline void PIT_ClearStatusFlags(PIT_Type *base, pit_chnl_t channel, uint32_t mask) { base->CHANNEL[channel].TFLG = mask; }

第一个参数PIT_Type *base:PIT,在MIMXRT1064.h中21006中30794 第二个参数 pit_chnl_t channel:可设置的通道如下

typedef enum _pit_chnl { kPIT_Chnl_0 = 0U, /*!< PIT channel number 0*/ kPIT_Chnl_1, /*!< PIT channel number 1 */ kPIT_Chnl_2, /*!< PIT channel number 2 */ kPIT_Chnl_3, /*!< PIT channel number 3 */ } pit_chnl_t;

第三个参数uint32_t mask:清除的中断标志位,这里只有 kPIT_TimerFlag 可选择. 通过向寄存器内写1,去清除标志位

typedef enum _pit_status_flags { kPIT_TimerFlag = PIT_TFLG_TIF_MASK, /*!< Timer flag */ } pit_status_flags_t; 示例 void PIT_CH0_Int_Init(uint32 ldval) { pit_config_t PIT_Config; //初始化PIT定时器 PIT_GetDefaultConfig(&PIT_Config); PIT_Config.enableRunInDbg=true; PIT_Init(PIT, &PIT_Config); //设置通道0的加载值,即LADVAL0的值 PIT_SetTimerPeriod(PIT,kPIT_Chnl_0,ldval); //使能通道0中断 PIT_EnableInterrupts(PIT,kPIT_Chnl_0,kPIT_TimerInterruptEnable); //开启PIT中断并设置优先级 NVIC_SetPriority(PIT_IRQn,10); //开启PIT定时器 PIT_StartTimer(PIT,kPIT_Chnl_0); } void PIT_IRQHandler(void) { if(PIT_GetStatusFlags(PIT,kPIT_Chnl_0)==kPIT_TimerFlag) { //do what PIT_ClearStatusFlags(PIT,kPIT_Chnl_0,kPIT_TimerFlag); } __DSB(); }

本文参照正点原子RT1052 开发指南修改编辑。 作者的软件基于逐飞部分库和fsl库开发



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3