ARM裸机开发:EPIT定时器
ARM裸机开发:EPIT定时器
一、硬件平台:
正点原子I.MX6U阿尔法开发板
二、原理分析
I.MX6U 提供了多种硬件定时器,有些定时器功能强大;本章 EPIT 定时器是其最基本的定时器!
2.1 EPIT 定时器简介
EPIT 全称:Enhanced Periodic Interrupt Timer(增强的周期中断定时器),用于完成周期性中断定时;
在 STM32 中,单片机的定时器除了周期性中断定时之外,还可以进行输入捕获和 PWM 输出功能,而 EPIT 仅支持周期性中断定时功能;
EPIT 是一个 32 位定时器,有如下特点:
时钟源可选的 32 位向下计数器
12 位的分频值
当计数值和比较值相等的时候产生中断
定时器结构如图:
其原理路线如下:
通过 1 选择时钟源,经过 12 位的分频器 2 进行分频,分频后的时钟提供给 32 位的计数寄存器 3,计数寄存器(EPIT_CNR)向下计数,通过比较器 4 和 32 位的比较寄存器(EPIT_CMPR)进行比较,到达计数周期后从加载寄存器(EPIT_LR)重新加载计数值,同时产生一个比较事件 6,也可以设置引脚输出,如果设置了的话就会通过指定的引脚输出信号,对应图中 5 ;
EPIT 定时器有两种工作模式:
set-and-forget 模式:
在此模式下 EPIT 的计数器从加载寄存器 EPITx_LR 中获取初始值,不能直接向计数器寄存 器写入数据,只要计数器计数到 0,那么就会从加载寄存器 EPITx_LR 中重新 加载数据到计数器中
free-running 模式:
作在此模式下,当计数器计数到0以后会重新从0XFFFFFFFF开始计数,并不是从加载寄存器EPITx_LR中获取数据
2.2 EPIT 主要寄存器
EPIT 的配置寄存器 EPITx_CR
主要位:
位 功能
CLKSRC(bit25:24) EPIT 时钟源选择位
0 的时候关闭时钟源
1 的时候选择选择Peripheral 时钟(ipg_clk)
2 的时候选择 High-frequency 参考时钟(ipg_clk_highfreq)
3 的时候选择 Low-frequency 参考时钟(ipg_clk_32k)
PRESCALAR(bit15:4) EPIT 时钟源分频值,可设置范围 0~4095,分别对应 1~4096 分频
RLD(bit3) EPIT 工作模式
0 的时候工作在 free-running 模式
1 的时候工作在 setand-forget 模式
OCIEN(bit2) 比较中断使能位
0 的时候关闭比较中断
1 的时候使能比较中断
ENMOD(bit1) 设置计数器初始值
0 时计数器初始值等于上次关闭 EPIT 定时器以后计数器里面的值
1 的时候来源于加载寄存器
EN(bit0) EPIT 使能位
0 的时候关闭 EPIT
1 的时候使能 EPIT
EPITx_SR 标志寄存器:
只有一个位有效,那就是 OCIF (bit0),这个位是比较中断标志位,为 0 的 时候表示没有比较事件发生,为 1 的时候表示有比较事件发生。
比较中断发生以后需要手动清除此位,此位是写 1 清零的
2.3 EPIT 使用方式
使用步骤流程如下:
设置 EPIT1 的时钟源
设置寄存器 EPIT1_CR 寄存器的 CLKSRC(bit25:24)位,选择 EPIT1 的时钟源
设置分频值
设置寄存器 EPIT1_CR 寄存器的 PRESCALAR(bit15:4)位,设置分频值
设置工作模式
设置寄存器 EPIT1_CR 的 RLD(bit3)位,设置 EPTI1 的工作模式
设置计数器的初始值来源
设置寄存器 EPIT1_CR 的 ENMOD(bit1)位,设置计数器的初始值来源
使能比较中断
我们要使用到比较中断,因此需要设置寄存器 EPIT1_CR 的 OCIEN(bit2)位,使能比较中断
设置加载值和比较值
设置寄存器 EPIT1_LR 中的加载值和寄存器 EPIT1_CMPR 中的比较值,通过这两个寄存器就可以决定定时器的中断周期
EPIT1 中断设置和中断服务函数编写
使能 GIC 中对应的 EPIT1 中断,注册中断服务函数,如果需要的话还可以设置中断优先级。最后编写中断服务函数
使能 EPIT1 定时器
通过寄存器 EPIT1_CR 的 EN(bit0)位来设置
三、程序编写
本节在上一章按键输入中断的过程下继续扩展,先复制一遍工程,然后添加 bsp_epit 文件夹和模块
模块 .h 头文件:
#ifndef __BSP_EPIT_H
#define __BSP_EPIT_H
#include "imx6ul.h"void epit_init(unsigned int frac,unsigned int value);
void epit_irqhandler(void);#endif
模块 .c 文件:
#include "bsp_epit.h"
#include "bsp_int.h"
#include "bsp_led.h"
//初始化函数
void epit_init(unsigned int psc,unsigned int value)
{if(psc>0xfff)psc=0xfff;EPIT1->CR = 0;EPIT1->CR = (1<<24 | psc<<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)epit_irqhandler,NULL);EPIT1->CR = 1<<0;
}
//定时器中断回调函数
void epit_irqhandler(void)
{static unsigned char sta = 0;sta = !sta;if(EPIT1->SR & (1<<0)){if(sta)LED_ON();elseLED_OFF();}EPIT1->SR |= 1<<0;
}
主函数代码:
#include "bsp_led.h"
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_exit.h"
#include "bsp_epit.h"
#include "imx6ul.h"
int main(void)
{
CLK_INIT();
int_init();
BSP_KEY_INIT();
LED_INIT();
exit_init();
//设置定时器的分频为1,加载寄存器值为 66000000/2=33000000
//即定时器中断周期为 500ms
epit_init(0,66000000/2);
while (1)
{
/* code */
delay(100);
}
return 0;
}
修改 Makefile 添加编译路径:
make 一下,编译通过,下载程序
四、实验现象
可以看到 LED 灯周期性的闪烁,跳变间隔约 0.5 S
————————————————
版权声明:本文为CSDN博主「Top嵌入式」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45396672/article/details/121380440
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
