一 简介
EPIT定时器是一种增强的周期中断定时器,完成周期性中断定时的功能。
具有以下特点
- EPIT定时器是一个32位的定时器
- 时钟源可选的向下计数器 EPIT 共有 3 个时钟源可选择,ipg_clk、ipg_clk_32k 和 ipg_clk_highfreq
- 当计数值和比较值相等的时候产生中断
- 12 位分频器 对应的值是 0~4095,对应1~4096 分频
- EPIT定时器在处理器几乎不用介入的情况下提供精准的定时中断,时序分辨率高达125fs。它可以应用于高速数据采集、超声波测距、雷达等领域。
- 可以设置引脚输出,如果设置了的话就会通过指定的引脚输出信号。
二 结构原理图
2.1 工作原理
图中 EPIT 内部有三个重要的寄存器:
计数寄存器(EPIT_CNR)、加载寄存器(EPIT_LR)和比较寄存器(EPIT_CMPR),
EPIT 是一个向下计数器,也就是说给它一个初值,开始递减,直到减 为 0,EPIT_CNR 里面保存的就是当前的计数值。如果 EPIT 工作在 set-and-forget 模式下,当计数寄存器里面的值减少到 0,EPIT 就会重新从EPIT_LR读取数值到计数寄存器里面,重新开 始向下计数。比较寄存器 EPIT_CMPR 里面保存的数值用于和计数寄存器里面的计数值比较,如果相等的话 就会产生一个比较事件。
2.2 工作模式
两种工作模式: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中获取数据。
2.3 23.6.1 Control register (EPITx_CR)
2.3.1 EPITx_CR field descriptions 位字段描述
寄存器 EPITx_CR 重要位如下:
CLKSRC(bit25:24): EPIT 时钟源选择位,
为 0 的时候关闭时钟源,
为1 的时候选择选择Peripheral 时钟(ipg_clk),
为 2 的时候选择 High-frequency 参考时钟(ipg_clk_highfreq),
为 3 的时候选择 Low-frequency 参考时钟(ipg_clk_32k)。
一般选择 ipg_clk=66MHz。
PRESCALAR(bit15:4): EPIT 时钟源分频值,可设置范围 0~ 4095,分别对应 1~ 4096 分频。
RLD(bit3): EPIT 工作模式,
为 0 的时候工作在 free-running 模式,
为 1 的时候工作在 set-and-forget 模式。
一般工作在 set-and-forget 模式。
OCIEN(bit2):比较中断使能位,
为 0 的时候关闭比较中断,
为 1 的时候使能比较中断,
本章试验要使能比较中断。
ENMOD(bit1):设置计数器初始值,
为 0 时计数器初始值等于上次关闭 EPIT 定时器以后计数器里面的值,
为 1 的时候来源于加载寄存器。
EN(bit0): EPIT 使能位,
为 0 的时候关闭 EPIT,
为 1 的时候使能 EPIT。0
2.4 EPIT_SR寄存器
EPIT_SR寄存器,只有bit0有效,表示中断状态,写1清零。当OCIF位为1的时候表示中断发生,为0的时候表示中断未发生。我们处理完定时器中断以后一定要清除中断标志位。
2.5 EPIT_LR 寄存器
EPIT_LR寄存器设置计数器的加载值。计数器每次计时到0以后就会读取LR寄存器的值重新开始计时。
2.6 EPIT_CMPR 寄存器
CMPR比较计数器,当计数器的值和CMPR相等以后就会产生比较中断。无需设置
3 使用实验
通过 EPTI1 的中断来控制 LED0 的亮灭 500ms一次中断,
3.1 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)位来设置。
驱动编写
- 配置EPIT1
- 使能对应中断
- 注册中断 服务函数
- 使能EPIT1
EPIT1->CR = (1<<24 | frac << 4 | 1<<3 | 1<<2 | 1<<1); 一次配置完EPIT1_CR寄存器
/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名 : bsp_epittimer.c
作者 : 左忠凯
版本 : V1.0
描述 : EPIT定时器驱动文件。
其他 : 配置EPIT定时器,实现EPIT定时器中断处理函数
论坛 : www.wtmembed.com
日志 : 初版V1.0 2019/1/5 左忠凯创建
***************************************************************/
#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; /* 清除中断标志位 */
}
3.2 分频计算方法
bit25:24 01 时钟源选择Peripheral clock=66MHz 设置分频值1 则计时计数器为 66*1000*1000/1*0.5 = 33000 000
epit1_init(0, 66000000/2); /* 初始化EPIT1定时器,1分频
* 计数值为:66000000/2,也就是
* 定时周期为500ms。
*/