EPIT定时器

一、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<<24 | 1<<3 | 1<<2 | 1<<1);

	/* 计数值    */
	EPIT1->LR = value;
	
	/* 比较寄存器,当计数器值和此寄存器值相等的话就会产生中断 */
	EPIT1->CMPR	= 0;	
	
	GIC_EnableIRQ(EPIT1_IRQn);	/* 使能GIC中对应的中断 */
	
	/* 注册中断服务函数		    */
	system_register_irqhandler(EPIT1_IRQn, (system_irq_handler_t)filtertimer_irqhandler, NULL);	
}

void filtertimer_stop(void)
{
	EPIT1->CR &= ~(1<<0);	/* 关闭定时器 */
}

void filtertimer_restart(unsigned int value)
{
	EPIT1->CR &= ~(1<<0);	/* 先关闭定时器 */
	EPIT1->LR = value;		/* 计数值 			*/
	EPIT1->CR |= (1<<0);	/* 打开定时器 		*/
}

/*中断服务函数*/
void filtertimer_irqhandler(void)
{ 
	static unsigned char state = OFF;

	if(EPIT1->SR & (1<<0)) 					/* 判断比较事件是否发生			*/
	{
		filtertimer_stop();					/* 关闭定时器 				*/
		if(gpio_pinread(GPIO1, 18) == 0)	/* KEY0 				*/
		{
			state = !state;
			beep_switch(state);				/* 反转蜂鸣器 				*/
		}
	}
		
	EPIT1->SR |= 1<<0; 						/* 清除中断标志位 				*/
}

定时器的初始化主要是对各个寄存器的设置,在定时器的中断服务函数处理按键。按键按下后,按键的中断服务函数会开启EPIT的定时器,当定时器发生溢出后,定时器就会产生比较事件,然后关闭定时器,读取IO的值,若为低电平,则按键发生了。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: i.MX6 EPIT(Enhanced Periodic Interrupt Timer)是一种双向计时器,可用于实现嵌入式Linux中的计时器功能,如周期性中断、定期任务等。 i.MX6 EPIT定时器驱动是在Linux内核中实现EPIT的驱动程序,可通过/sys/class/timer/epit目录下的文件进行控制。该驱动程序使用了内核中的定时器子系统,支持定时器的配置、开启、关闭和重启功能。 EPIT定时器具有多种模式,可实现周期性中断、单次计时、连续计时等。驱动程序提供了获取当前定时器计数器和比较器值、设置比较器值、配置定时器模式和时钟源等接口。 在应用程序中,可以利用EPIT定时器驱动实现心跳包发送、数据采集、定时任务等功能。例如,定期采集传感器数据可以使用连续计时模式,每隔一段时间触发一次中断,读取传感器数据并进行处理,以便实现对数据的实时监测和分析。 总之,i.MX6 EPIT定时器驱动在嵌入式Linux系统中具有广泛的应用场景,是实现计时器功能的重要组成部分。 ### 回答2: i.mx6 epit定时器驱动是一种用于控制时间计数和时序操作的驱动程序。i.mx6 epit定时器驱动是针对ARM架构的一种硬件计时器,其可在一定时间范围内对计时周期进行划分,并且在计时到达特定时间节点时可以触发相应的中断信号。这种特性有助于对系统中各个模块的时间操控和协同进行更加精确和高效的管理。 在实现i.mx6 epit定时器驱动时,需要首先对硬件的时钟和计数器进行初始化,同时规划好所需要的计时周期及其对应的中断服务程序。其次,需要根据实际应用场景,选择合适的工作模式,比如定时器的循环工作模式和单次工作模式等。此外,i.mx6 epit定时器驱动还可通过设置各种定时器的触发条件、分频系数、计数器值、预定中断周期等参数来指导其工作。 i.mx6 epit定时器驱动在实际应用中,可以用于很多领域比如:测量仪、定时器、中断控制、数据采集、总线同步、状态监测等。同时,在多任务操作系统中,也可以将i.mx6 epit定时器驱动与系统时钟的管理器进行集成,以实现更加高效和稳定的系统时间管理。 综上所述,i.mx6 epit定时器驱动是一种用于时间计数和时序操作的驱动程序,具有精确高效的特点,并且在多领域应用中有着广泛的应用价值。 ### 回答3: i.MX6 EPIT (Enhanced Periodic Interval Timer)是一种高级计时器,用于基于ARM Cortex-A9的i.MX6处理器。它具有精确的定时器功能和多种配置选项,可用于实现高精度周期性操作,如定时中断、PWM (脉宽调制)等。在嵌入式系统中,i.MX6 EPIT常用于实现精确定时、控制外设、任务切换等功能。 驱动i.MX6 EPIT定时器需要在内核中实现一个设备驱动程序。该驱动程序需要完成以下几个主要任务: 1. 初始化EPIT定时器,包括设置时钟源、预分频、计数模式、计时周期等。 2. 响应定时器中断,即在定时器达到预定的时间时触发中断。在中断处理程序中,可以执行相应的操作,如更新任务状态、控制外设、发送信号等。 3. 提供用户接口,允许应用程序通过ioctl系统调用配置和控制定时器。例如,可以通过ioctl命令来设置定时周期、使能定时器、暂停定时器等。 在实现EPIT定时器驱动时,需要注意以下几个关键点: 1. 时钟源选择。i.MX6处理器内部有多个时钟源可供选择,如ARM内核时钟、PLL时钟、外部时钟输入等。需要根据应用场景选择适合的时钟源,并进行相应的配置。 2. 计时精度。EPIT定时器的计时精度可以通过预分频系数和计数位宽来控制。需要根据具体需求进行合理的配置,以实现满足精度要求的定时功能。 3. 中断处理。在中断处理程序中,需要注意避免阻塞和死锁问题,防止同时发生多个中断导致系统崩溃。 4. 设备节点的创建和管理。通过设备节点,驱动程序可以与用户空间的应用程序进行交互。需要正确创建和管理设备节点,保证应用程序与驱动之间的通信正常进行。 总之,实现i.MX6 EPIT定时器驱动需要对硬件及其编程接口有一定的了解,同时结合系统需求进行合理的配置和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super.Bear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值