您当前的位置: 首页 > 

风间琉璃•

暂无认证

  • 1浏览

    0关注

    337博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

EPIT定时器

风间琉璃• 发布时间:2022-02-06 18:33:51 ,浏览量:1

一、EPIT原理

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            
关注
打赏
1665385461
查看更多评论
0.0361s