嵌入式技术
大家好,我是ST。
今天的话主要和大家聊一聊,如何使用定时器,完成精准的定时功能实现。
第一:EPIT定时器基本简介
EPIT 的全称是:Enhanced Periodic Interrupt Timer,直译过来就是增强的周期中断定时器,它主要是完成周期性中断定时的。学过 STM32 的话应该知道,STM32 里面的定时器还有很多其它的功能,比如输入捕获、PWM 输出等等。 EPIT 定时器只是完成周期性中断定时的,仅此一项功能!至于输入捕获、PWM 输出等这些功能,由其它的外设来完成。
EPIT是一个32位定时器,在处理的时候提供精准的定时中断,软件使能以后EPIT就会开始运行,EPIT定时器有如下特点:
1、时钟源可选的32位向下计数器。
2、12位的分频值。
3、当计数值和比较值相等的时候产生中断。
各个部分的功能:
①、这是个多路选择器,用来选择EPIT定时器的时钟源,EPIT 共有 3 个时钟源可选择,ipg_clk、ipg_clk_32k 和 ipg_clk_highfreq。
②、这是一个 12 位的分频器,负责对时钟源进行分频,12 位对应的值是 0~4095,对应着1~4096 分频。
③、经过分频的时钟进入到 EPIT 内部,在 EPIT 内部有三个重要的寄存器:计数寄存器(EPIT_CNR)、加载寄存器(EPIT_LR)和比较寄存器(EPIT_CMPR),这三个寄存器都是 32 位的。EPIT 是一个向下计数器,也就是说给它一个初值,它就会从这个给定的初值开始递减,直到减为 0,计数寄存器里面保存的就是当前的计数值。如果 EPIT 工作在 set-and-forget 模式下,当计数寄存器里面的值减少到 0,EPIT 就会重新从加载寄存器读取数值到计数寄存器里面,重新开始向下计数。比较寄存器里面保存的数值用于和计数寄存器里面的计数值比较,如果相等的话就会产生一个比较事件。
④、比较器。
⑤、EPIT 可以设置引脚输出,如果设置了的话就会通过指定的引脚输出信号。
⑥、产生比较中断,也就是定时中断。
第二:EPIT的基本配置
1、设置 EPIT1 的时钟源设置寄存器 EPIT1_CR 寄存器的 CLKSRC(bit25:24)位,选择 EPIT1 的时钟源。
2、设置分频值设置寄存器 EPIT1_CR 寄存器的 PRESCALAR(bit15:4)位,设置分频值。
3、设置工作模式设置寄存器 EPIT1_CR 的 RLD(bit3)位,设置 EPTI1 的工作模式。
4、设置计数器的初始值来源设置寄存器 EPIT1_CR 的 ENMOD(bit1)位,设置计数器的初始值来源。
5、使能比较中断我们要使用到比较中断,因此需要设置寄存器 EPIT1_CR 的 OCIEN(bit2)位,使能比较中断。
6、设置加载值和比较值设置寄存器 EPIT1_LR 中的加载值和寄存器 EPIT1_CMPR 中的比较值,通过这两个寄存器就可以决定定时器的中断周期。
7、EPIT1 中断设置和中断服务函数编写使能 GIC 中对应的 EPIT1 中断,注册中断服务函数,如果需要的话还可以设置中断优先级。最后编写中断服务函数。
8、使能 EPIT1 定时器配置好 EPIT1 以后就可以使能 EPIT1 了,通过寄存器 EPIT1_CR 的 EN(bit0)位来设置。通过以上几步我们就配置好 EPIT 了,通过 EPIT 的比较中断来实现 LED0 的翻转。
第三:代码的具体实现
#include "bsp_epittimer.h" #include "bsp_int.h" #include "bsp_led.h" /* * @description : 初始化 EPIT 定时器. * EPIT 定时器是 32 位向下计数器,时钟源使用 ipg=66Mhz * @param – frac : 分频值,范围为 0~4095,分别对应 1~4096 分频。 * @param - value : 倒计数值。 * @return : 无 */ void epit1_init(unsigned int frac, unsigned int value) { if(frac > 0XFFF) frac = 0XFFF; EPIT1->CR = 0; /* 先清零 CR 寄存器 */ /* * CR 寄存器: * bit25:24 01 时钟源选择 Peripheral clock=66MHz * bit15:4 frac 分频值 * bit3: 1 当计数器到 0 的话从 LR 重新加载数值 * bit2: 1 比较中断使能 * bit1: 1 初始计数值来源于 LR 寄存器值 * bit0: 0 先关闭 EPIT1 */ EPIT1->CR = (1<<24 | frac << 4 | 1<<3 | 1<<2 | 1<<1); EPIT1->LR = value; /* 加载寄存器值 */ EPIT1->CMPR = 0; /* 比较寄存器值 */ /* 使能 GIC 中对应的中断 */ GIC_EnableIRQ(EPIT1_IRQn); /* 注册中断服务函数 */ system_register_irqhandler(EPIT1_IRQn,(system_irq_handler_t)epit1_irqhandler, NULL); EPIT1->CR |= 1<<0; /* 使能 EPIT1 */ } /* * @description : EPIT 中断处理函数 * @param : 无 * @return : 无 */ void epit1_irqhandler(void) { static unsigned char state = 0; state = !state; if(EPIT1->SR & (1<<0)) /* 判断比较事件发生 */ { led_switch(LED0, state); /* 定时器周期到,反转 LED */ } EPIT1->SR |= 1<<0; /* 清除中断标志位 */ }
总结:EPIT定时器的处理方法,不同的芯片会有所差别,但是总体上,区别不大。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !