【ARM学习笔记】ARM Cortex -A7 EPIT定时器

简述

ARM Cortex-A7的一个定时器,用来完成周期性中断定时
特点:

  1. 时钟源可选的32位向下计数器
  2. 12位的分频值
  3. 当计数值和比较值相等的时候产生中断
  4. 可以即使编程的计数器值
  5. 在低功耗和调试模式下能够编程为活跃状态

原理分析

结构分析

在这里插入图片描述

  1. 多路选择器,共有三个时钟源可选择:
    1. ipg_clk:由时钟控制模块CCM提供的Peripheral clock;
    2. ipg_clk_32k:低频率参考时钟,32kHz的参考时钟,来自外部的32kHz晶振;
    3. ipg_clk_highfreq:由时钟控制模块CCM提供的高频率参考时钟。
  2. 12bit的预分频器,对时钟源进行分频,12bit对应的值为04095,也就是可以设置为14096分频。
  3. EPIT内部,三个重要的寄存器(32位):
    1. Counter Register,计数寄存器,EPIT是一个向下计数的定时器,给予它一个初值,便会从这个初始值开始递减,直到为0,Counter Register就保存了当前的计数值。
    2. Load Register为装载寄存器,当EPIT被设置为set-and-forget模式,当计数器递减到0后,EPIT就会读取Load Register保存的值到Counter Register,并且重新开始计数。
    3. Compare Register为比较寄存器,用于和Counter Register中的值进行比较,如果相等的话能产生一个比较事件。
  4. 比较器,比较Compare Register和Counter Register中的值,相等即产生比较事件
  5. 设置外设引脚输出,指定引脚输出信号。
  6. 定时中断。

工作模式

两种工作模式: set-and-forget 和 free-running ,通过EPIT_CR[RLD]能设置

  • 当EPIT_CR寄存器的RLD被置1的时候,EPIT工作在set-and-forget模式,在该模式下,EPIT定时器的计数值从LoadRegister中获取初始值,此时不能直接向CounterRegister中写入数据,当计数器的值递减为0后,将会从LoadRegister中加载数据到计数器,周而复始运行。
  • 当EPIT_CR寄存器的RLD被清0的时候,EPIT工作在free-running模式,当计数器的值到0后,计数器的值会进行翻转变为0xFFFF_FFFF,并重新开始计数,而不是从Load Register中获取数据;

寄存器(部分)

寄存器EPITx_CR,用来配置EPIT
在这里插入图片描述

CLKSRC(bit[25:24]):用来设置EPIT的时钟源

- CLKSRC时钟源
00关闭时钟源
01Peripheral 时钟
10High-frequency
11Low-frequency
  • PRESCALAR(bit[15:4]):EPIT时钟源的预分频值,12bit,能设置的值为0x0000xFFF,对应分频的值为14096。

  • RLD(bit3):用于设置EPIT的工作模式,该bit为0的时候工作在free-running模式,为1的时候工作在set-and-forget模式。

  • OCIEN(bit2):比较中断使能位,设置为0的时候将禁止比较中断,设置为1的时候将使能比较中断。

  • ENMOD(bit1):用来设置计数器的初始值,设置为0时,计数器的初始值等于上次关闭EPIT定时器中计数器的值,设置为1时,初始值取决于RLD的配置,如果RLD=1时,计数器的值来源于Load Register,如果RLD=0,则计数器的值为0xFFFF_FFFF。

  • EN(bit0):EPIT定时器使能位。0闭,1使能


寄存器EPITx_SR,只有最低位(OCIF(bit0))有效,比较中断标识位,0的时候无比较事件发生,1的时候有比较时间发生。需手动清零。

溢出时间计算

溢出时间 = ((分频值+1)*装载值)/时钟频率

配置流程

  1. 设置时钟来源,通过EPIT_CR寄存器的CLKSRC位选择
  2. 设置定时器的预分频值,通过设置EPITx_CR寄存器中的PRESCALAR,配置EPIT定时器时钟分频值
  3. 设置工作方式,置EPITx_CR寄存器中的RLD
  4. 设置定时器中计数器的初始值来源,通过设置EPITx_CR的ENMOD(bit1),配置计数器的初值来源
  5. 使能比较中断,设置EPITx_CR的OCIEN位,置1
  6. 设置加载值(装载值)和比较值,设置EPITx_LR和EPITx_CMPR寄存器
  7. 中断服务函数
  8. 使能EPIT

实现过程

功能描述

通过EPTI1控制LED的亮灭。

代码编写(部分)

/***************************
 File name: bsp_epit
 Author: ori
 Version: v1.0
 Description: EPIT驱动文件
 Others: 无
 log: 2021/2/2
 ***************************/
#include "bsp_epit.h"
#include "bsp_int.h"
#include "bsp_led.h"

/*
 * @description     :EPIT1初始化
 * @param - frac    :分频
 * @param - value   :装载值
 * @return          :0
 */
void epit1_init(unsigned int frac, unsigned int value)
{
    if(frac > 0XFFF)
        frac = 0XFFF;   /* 这里先设置为最大分频 */
    EPIT1->CR = 0;      /* 清零CR寄存器,为了方便后续配置 */

    /* 66MHz,分频值为4,set-and-forget工作模式,值来源load register */
    EPIT1->CR = (1<<24 | frac << 4 | 1 << 3 | 1 << 2 | 1 << 1);
    EPIT1->LR = value;  /* 加载寄存器值 */
    EPIT1->CMPR = 0;    /* 比较寄存器值 */

    /* 使能中断 */
    GIC_EnableIRQ(EPIT1_IRQn); 

    /* 注册中断服务函数 */
    system_register_irqhandler(EPIT1_IRQn, (system_irq_handler_t)epit1_irqhandler, NULL);	

    /* 使能EPIT1 */ 
	EPIT1->CR |= 1<<0;	

}

/*
 * @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; 				/* 清除中断标志位 */
}

/***************************
 File name: bsp_epit
 Author: ori
 Version: v1.0
 Description: EPIT驱动头文件
 Others: 无
 log: 2021/2/2
 ***************************/
#ifndef _BSP_EPIT_H
#define _BSP_EPIT_H

#include"imx6ul.h"

void epit1_init(unsigned int frac, unsigned int value);

void epit1_irqhandler(void);




#endif // !1
/***************************
 File name: bsp_epit
 Author: ori
 Version: v1.0
 Description: EPIT练习
 Others: 无
 log: 2021/2/2
 ***************************/
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_exit.h"
#include "bsp_epit.h"

/*
 * @description	: main函数
 * @param 		: 无
 * @return 		: 无
 */
int main(void)
{

	int_init(); 		/* 初始化中断(一定要最先调用!) */
	imx6u_clkinit();	/* 初始化系统时钟 			*/
	clk_enable();		/* 使能所有的时钟 			*/
	led_init();			/* 初始化led 			*/
	beep_init();		/* 初始化beep	 		*/
	key_init();			/* 初始化key 			*/
	exit_init();		/* 初始化按键中断			*/
	/* 初始化EPIT定时器,1分频,计数值33000000,500ms */
	epit1_init(0,33000000);


	while(1)			
	{	
		
		delay(500);
	}

	return 0;
}

编译烧录

在这里插入图片描述

最后

本文多处参考正点原子的课程和资料(特表感谢),并在此基础上进了扩展和自己的理解,最后自己动手复原例程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ORI2333

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

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

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

打赏作者

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

抵扣说明:

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

余额充值