RT1064学习笔记 |
您所在的位置:网站首页 › 定时器产生中断的频率是什么 › RT1064学习笔记 |
RT1064 周期中断定时器简介
PIT模块是一组计时器,可用于引发中断和触发DMA通道。 PIT定时器框图如下图所示:
本次任务 我们主要使用 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控制寄存器 MDIS 位,用于控制PIT 的时钟使能,0,使能;1,禁止。 FRZ 位,用于控制 PIT 在 Debug 模式下是否继续运行,0,Debug 模式继续运行;1,Debug 模式停止运行。 Timer Load Value Register (LDVAL0 - LDVAL3)通道加载值寄存器 所以,在时钟频率确定的前提下(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)通道控制寄存器 TIE 位[1]:用于设置是否使能中断功能。0,不使能;1,使能。如果使能,则在定时器通道计数到 0 的时候,将会产生中断。 TEN 位[2]:用于设置是否使能该通道。0,不使能;1,使能。本章我们需要用到通道 0,所以通道 0 的 TEN 位需要设置为 1。 Timer Flag Register (TFLG0 - TFLG3)通道标志寄存器
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 |