您当前的位置: 首页 >  嵌入式

正点原子

暂无认证

  • 3浏览

    0关注

    382博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【正点原子Linux连载】第十八章 EPIT定时器实验-摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

正点原子 发布时间:2021-08-23 11:24:16 ,浏览量:3

1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html 3)对正点原子Linux感兴趣的同学可以加群讨论:935446741 4)关注正点原子公众号,获取最新资料更新 在这里插入图片描述

第十八章 EPIT定时器实验

定时器是最常用的外设,常常需要使用定时器来完成精准的定时功能,I.MX6U提供了多种硬件定时器,有些定时器功能非常强大。本章我们从最基本的EPIT定时器开始,学习如何配置EPIT定时器,使其按照给定的时间,周期性的产生定时器中断,在定时器中断里面我们可以做其它的处理,比如翻转LED灯。

18.1 EPIT定时器简介 EPIT的全称是:Enhanced Periodic Interrupt Timer,直译过来就是增强的周期中断定时器,它主要是完成周期性中断定时的。学过STM32的话应该知道,STM32里面的定时器还有很多其它的功能,比如输入捕获、PWM输出等等。但是I.MX6U的EPIT定时器只是完成周期性中断定时的,仅此一项功能!至于输入捕获、PWM输出等这些功能,I.MX6U由其它的外设来完成。 EPIT是一个32位定时器,在处理器几乎不用介入的情况下提供精准的定时中断,软件使能以后EPIT就会开始运行,EPIT定时器有如下特点: ①、时钟源可选的32位向下计数器。 ②、12位的分频值。 ③、当计数值和比较值相等的时候产生中断。 EPIT定时器结构如图18.1.1所示: 在这里插入图片描述

图18.1.1 EPIT定时器框图 图18.1.1中各部分的功能如下: ①、这是个多路选择器,用来选择EPIT定时器的时钟源,EPIT共有3个时钟源可选择,ipg_clk、ipg_clk_32k和ipg_clk_highfreq。 ②、这是一个12位的分频器,负责对时钟源进行分频,12位对应的值是04095,对应着14096分频。 ③、经过分频的时钟进入到EPIT内部,在EPIT内部有三个重要的寄存器:计数寄存器(EPIT_CNR)、加载寄存器(EPIT_LR)和比较寄存器(EPIT_CMPR),这三个寄存器都是32位的。EPIT是一个向下计数器,也就是说给它一个初值,它就会从这个给定的初值开始递减,直到减为0,计数寄存器里面保存的就是当前的计数值。如果EPIT工作在set-and-forget模式下,当计数寄存器里面的值减少到0,EPIT就会重新从加载寄存器读取数值到计数寄存器里面,重新开始向下计数。比较寄存器里面保存的数值用于和计数寄存器里面的计数值比较,如果相等的话就会产生一个比较事件。 ④、比较器。 ⑤、EPIT可以设置引脚输出,如果设置了的话就会通过指定的引脚输出信号。 ⑥、产生比较中断,也就是定时中断。 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_LR中获取数据。 接下来看一下EPIT重要的几个寄存器,第一个就是EPIT的配置寄存器EPITx_CR,此寄存器的结构如图18.1.2所示: 在这里插入图片描述

图18.1.2 EPITx_CR寄存器结构图 寄存器EPITx_CR我们用到的重要位如下: CLKSRC(bit25:24):EPIT时钟源选择位,为0的时候关闭时钟源,1的时候选择选择Peripheral时钟(ipg_clk),为2的时候选择High-frequency参考时钟(ipg_clk_highfreq),为3的时候选择Low-frequency参考时钟(ipg_clk_32k)。在本例程中,我们设置为1,也就是选择ipg_clk作为EPIT的时钟源,ipg_clk=66MHz。 PRESCALAR(bit15:4):EPIT时钟源分频值,可设置范围04095,分别对应14096分频。 RLD(bit3):EPIT工作模式,为0的时候工作在free-running模式,为1的时候工作在set-and-forget模式。本章例程设置为1,也就是工作在set-and-forget模式。 OCIEN(bit2):比较中断使能位,为0的时候关闭比较中断,为1的时候使能比较中断,本章试验要使能比较中断。 ENMOD(bit1):设置计数器初始值,为0时计数器初始值等于上次关闭EPIT定时器以后计数器里面的值,为1的时候来源于加载寄存器。 EN(bit0):EPIT使能位,为0的时候关闭EPIT,为1的时候使能EPIT。 寄存器EPITx_SR结构体如图18.1.3所示: 在这里插入图片描述

图18.1.3 EPITx_SR寄存器结构图 寄存器EPITx_SR只有一个位有效,那就是OCIF(bit0),这个位是比较中断标志位,为0的时候表示没有比较事件发生,为1的时候表示有比较事件发生。当比较中断发生以后需要手动清除此位,此位是写1 清零的。 寄存器EPITx_LR、EPITx_CMPR和EPITx_CNR分别为加载寄存器、比较寄存器和计数寄存器,这三个寄存器都是用来存放数据的,很简单。 关于EPIT的寄存器就介绍到这里,关于这些寄存器详细的描述,请参考《I.MX6ULL参考手册》第1174页的24.6小节。本章我们使用EPIT产生定时中断,然后在中断服务函数里面翻转LED0,接下来以EPIT1为例,讲解需要哪些步骤来实现这个功能。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的翻转。 18.2 硬件原理分析 本试验用到的资源如下: ①、LED0。 ②、 定时器EPTI1。 本实验通过EPTI1的中断来控制LED0的亮灭,LED0的硬件原理前面已经介绍过了。 18.3 实验程序编写 本实验对应的例程路径为:开发板光盘-> 1、裸机例程-> 10_epit_timer。 本章实验在上一章例程的基础上完成,更改工程名字为“epit_timer”,然后在bsp文件夹下创建名为“epittimer”的文件夹,然后在bsp/epittimer中新建bsp_epittimer.c和bsp_epittimer.h这两个文件。在bsp_epittimer.h中输入如下内容: 示例代码18.3.1 bsp_epittimer.h文件代码

1  #ifndef _BSP_EPITTIMER_H
2  #define _BSP_EPITTIMER_H
3  /***************************************************************
4  Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
5  文件名    : bsp_epittimer.h
6  作者      : 左忠凯
7  版本      : V1.0
8  描述      : EPIT定时器驱动头文件。
9  其他      : 无
10 论坛      : www.openedv.com
11 日志      : 初版V1.0 2019/1/5 左忠凯创建
12 ***************************************************************/
13 #include "imx6ul.h"
14 
15 /* 函数声明 */
16 void epit1_init(unsigned int frac, unsigned int value);
17 void epit1_irqhandler(void);
18 
19 #endif
	bsp_epittimer.h文件很简单,就是一些函数声明。然后在bsp_epittimer.c中输入如下内容:
示例代码18.3.2 bsp_epittimer.c文件代码
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名   : bsp_epittimer.c
作者     : 左忠凯
版本     : V1.0
描述     : EPIT定时器驱动文件。
其他     : 配置EPIT定时器,实现EPIT定时器中断处理函数
论坛     : www.openedv.com
日志     : 初版V1.0 2019/1/5 左忠凯创建
***************************************************************/
1  #include "bsp_epittimer.h"
2  #include "bsp_int.h"
3  #include "bsp_led.h"
4  
5  /*
6   * @description   	: 初始化EPIT定时器.
7   *                      EPIT定时器是32位向下计数器,时钟源使用ipg=66Mhz      
8   * @param – frac	: 分频值,范围为0~4095,分别对应1~4096分频。
9   * @param - value 	: 倒计数值。
10  * @return         	: 无
11  */
12 void epit1_init(unsigned int frac, unsigned int value)
13 {
14  	if(frac > 0XFFF)
15      	frac = 0XFFF;
16  	EPIT1->CR = 0;  /* 先清零CR寄存器 */
17  
18  	/*
19 	  	 * CR寄存器:
20       * bit25:24 01 时钟源选择Peripheral clock=66MHz
21       * bit15:4  frac 分频值
22       * bit3: 1  当计数器到0的话从LR重新加载数值
23       * bit2: 1  比较中断使能
24       * bit1:    1  初始计数值来源于LR寄存器值
25       * bit0:    0  先关闭EPIT1
26       */
27  	EPIT1->CR = (1            
关注
打赏
1665308814
查看更多评论
0.0946s