EPIT(Enhanced Periodic Interrupt Timer): 增强的周期中断定时器,它主要是完成周期性中断定时的,EPIT 是一个 32 位定时器,在处理器几乎不用介入的情况下提供精准的定时中断,软件使能以后 EPIT 就会开始运行。时钟源可选的 32 位向下计数器,12 位的分频值,当计数值和比较值相等的时候产生中断
EPIT定时器结构:
(1)多路选择器,用来选择 EPIT 定时器的时钟源, EPIT 共有 3 个时钟源可选择,ipg_clk、 ipg_clk_32k 和 ipg_clk_highfreq。一般选择ipg_clk (66MHz)
(2)12 位的分频器,负责对时钟源进行分频, 12 位对应的值是 0~4095
(3)内部寄存器:计数寄存器(EPIT_CNR)、加载寄存器(EPIT_LR)和比较寄存器(EPIT_CMPR)
EPIT 定时器有两种工作模式: set-and-forget 和 free-running
set-and-forget 模式: EPITx_CR(x=1, 2)寄存器的 RLD 位置 1 的时候 EPIT 工作在此模式 下,在此模式下 EPIT 的计数器从加载寄存器 EPITx_LR 中获取初始值。只要计数器计数到 0,会从加载寄存器 EPITx_LR 中重新加载数据到计数器中。free-running 模式: EPITx_CR 寄存器的 RLD 位清零的时候 EPIT 工作在此模式下,当计数器计数到0以后会重新从0XFFFFFFFF开始计数
EPITx_CR寄存器
CLKSRC(bit25:24): EPIT 时钟源选择位,设置为 1,选择 ipg_clk(66MHZ)作为时钟源
PRESCALAR(bit15:4): EPIT 时钟源分频值,可设置范围 0~4095 RLD(bit3): EPIT 工作模式,设置为 1,工作在 set-and-forget 模式 OCIEN(bit2):比较中断使能位,为 0 时关闭比较中断,为 1 时使能比较中断 ENMOD(bit1):设置计数器初始值,为 0 时计数器初始值等于上次关闭 EPIT 定时器后 计数器里面的值,为 1 的时候来源于加载寄存器EN(bit0): EPIT 使能位,为 0 的时关闭 EPIT,为 1 的时使能 EPIT
寄存器 EPITx_SR 只有一个位有效:OCIF(bit0),这个位是比较中断标志位,为 0 的时表示没有比较事件发生,为 1 的时表示有比较事件发生。当比较中断发生以后需要手动清除此位,此位是写 1 清零的
寄存器 EPITx_LR、 EPITx_CMPR 和 EPITx_CNR 分别为加载寄存器、比较寄存器和计数寄 存器用来存放数据的
二、按键消抖
利用EPIT定时器处理按键消抖,在按键按下以后延时一段时间再去读取按键值,如果此时按键值还有效就表示这是一次有效的按键,中间的延时就是消抖,如果采用延时函数,会浪费CPU性能。
按键采用中断驱动方式,当按键按下以后触发按键中断,在按键中断中开启一个定时器,定时周期为 10ms,当定时时间到了以后就会触发定时器中断,最后在定时器中断处理函数中读取按键的值,如果按键值还是按下状态就表示这是一次有效的按键
t1~t3 这一段时间是按键抖动,是需要消除的。设置按键为下降沿触发,在 t1、 t2 和 t3 这三个时刻会触发按键中断,每次进入中断处理函数都会重新开器定时器中断,所以会在 t1、 t2 和 t3 这三个时刻开器定时器中断
但是 t1~t2 和 t2~t3 这两个时间段是小于设置的定时器中断周期(也就是消抖时间,比如 10ms),所以虽然 t1 开启了定时器,但是定时器定时时间还没到呢 t2 时刻就重置了定时器,最终只有 t3 时刻开启的定时器能完整的完成整个定时周期并触发中断,于是在中断处理函数里面做按键处理,这就是定时器实现按键防抖的原理, Linux 按键驱动也是这个原理
按键中断初始化和按键中断服务函数
void filterkey_init(void)
{
gpio_pin_config_t key_config;
/* 1、初始化IO复用 */
IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0); /* 复用为GPIO1_IO18 */
/* 2、、配置GPIO1_IO18的IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 11 默认22K上拉
*bit [13]: 1 pull功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 000 关闭输出
*bit [0]: 0 低转换率
*/
IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);
/* 3、初始化GPIO为中断 */
key_config.direction = kGPIO_DigitalInput;
key_config.interruptMode = kGPIO_IntFallingEdge;
key_config.outputLogic = 1;
gpio_init(GPIO1, 18, &key_config);
GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); /* 使能GIC中对应的中断 */
/* 注册中断服务函数 */
system_register_irqhandler(GPIO1_Combined_16_31_IRQn,
(system_irq_handler_t)gpio1_16_31_irqhandler,
NULL);
gpio_enableint(GPIO1, 18); /* 使能GPIO1_IO18的中断功能 */
filtertimer_init(66000000/100); /* 初始化定时器,10ms */
}
void gpio1_16_31_irqhandler(void)
{
/* 开启定时器 */
filtertimer_restart(66000000/100);
/* 清除中断标志位 */
gpio_clearintflags(GPIO1, 18);
}
在按键初始化里面进行对GPIO中断的配置,并完成相应的GIC,GPIO使能和定时器的初始化,主要是设置周期。按键中断服务函数里面就仅仅开启EPIT定时器和清除定时器的中断标志位。
EPIT定时器的初始化和定时器的中断服务函数
void filtertimer_init(unsigned int value)
{
EPIT1->CR = 0; //先清零
/*
* CR寄存器:
* bit25:24 01 时钟源选择Peripheral clock=66MHz
* bit15:4 0 1分频
* bit3: 1 当计数器到0的话从LR重新加载数值
* bit2: 1 比较中断使能
* bit1: 1 初始计数值来源于LR寄存器值
* bit0: 0 先关闭EPIT1
*/
EPIT1->CR = (1
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?