一. EPIT中断定时器
EPIT定时器:一种中断定时器。详细的介绍可以参考上一篇文章:
IMX6ULL裸机篇之按键中断实验_凌雪舞的博客-CSDN博客
本文学习一下 EPIT定时器的使用。实现如下功能:
实现 500ms 周期的定时器。
我们在 EPIT中断服务函数里,实现 LED灯亮灭。
二. EPIT中断定时器实验
1. EPIT中断定时器实验工作
(1) 设置 EPIT1 的时钟源,工作模式,时钟源选择,分频值,使能比较中断等。EPITx_CR 寄存器设置。
分频值与计数器加载值计算公式如下:
Tout = ((frac +1 )* value) / Tclk;
(2) EPIT1 中断设置
(3) 使能 GIC 中对应的 EPIT1 中断,注册中断服务函数。
如果需要,还可以设置中断优先级。
2. 计算计数加载值
分频值与计数器加载值计算公式如下:
Tout = ((frac +1 )* value) / Tclk;
其中,frac 是分频数,value 为待计算的计数加载值。
Tclk : EPIT1 的输入时钟频率(单位 Hz)。
Tout:EPIT1 的溢出时间(单位 S)。
时钟源的选择由如下四种。配置选择 ipg_clk 为时钟源。根据之前时钟源章节,可以知道 ipg_clk 时钟源提供了 66 MHZ的时钟频率。
秒与频率换算关系: 秒 = 1 / 频率。
这里选择 配置为 1 分频,即 frac 值为 0。
这个实验实现 500ms定时,即 Tout 值为 0.5 s(500 ms == 0.5s)
Tclk 是由 ipg_clk时钟源提供,由之前时钟实验可以知道, ipg_clk时钟频率为 66 MHZ,即 Tclk 是 66MHZ。
通过以上公式计算可得:
value = (Tout * Tclk)/(0+1)
value = (0.5* 66000000HZ) = 33000000
3. 代码实现
#ifndef _BSP_EPIT_H_
#define _BSP_EPIT_H_
#include "imx6ull.h"
void epit1_init(unsigned int freq_value, unsigned int reload_value);
void epit1_irq_hander(unsigned int gicciar, void* param);
#endif
bsp_epittimer.c文件代码如下:
#include "bsp_epit.h"
#include "bsp_int.h"
#include "bsp_led.h"
/* 初始化EPIT */
//freq_value: 分频数
//reload_value: 计数器加载值
void epit1_init(unsigned int freq_value, unsigned int reload_value)
{
if(freq_value > 4095)
{
freq_value = 4095;
}
//配置EPIT1定时器的EPIT_CR寄存器
EPIT1->CR = 0;
EPIT1->CR = ((1 << 1)|(1 << 2)|(1 << 3)|(freq_value << 4)|(1 << 24));
//配置EPITx_LR寄存器加载值(相当于倒计数器)
EPIT1->LR = (reload_value << 0);
EPIT1->CMPR = 0; //配置EPITx_CMPR寄存器的比较值
/*初始化中断 */
GIC_EnableIRQ(EPIT1_IRQn); //初始化GIC控制器
/*注册中断函数 */
system_register_irqhandler(EPIT1_IRQn, epit1_irq_hander, NULL);
//使能 EPIT1定时器
EPIT1->CR |= (1 << 0);
}
/* EPIT中断服务函数 */
void epit1_irq_hander(unsigned int gicciar, void* param)
{
static unsigned int led_status = 0;
led_status = !led_status;
//判断中断标志位
if(EPIT1->SR & (1 <<0)) //中断已发生
{
led_switch(LED0, led_status);
}
//清除中断标志位(注意:是写1清零!!!)
EPIT1->SR |= (1 << 0);
}
主函数 main.c 中,添加定时器 EPIT1 的初始化,去掉 while 循环中涉及 LED 灯的操作。
main.c 代码如下:
#include "imx6ull.h"
#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_exter_int.h"
#include "bsp_epit.h"
int main(void)
{
int_init(); //中断初始化
imux6ull_clk_init(); //初始化系统时钟
clk_enable(); //使能外设时钟
led_init(); //Led初始化
beep_init(); //蜂鸣器初始化
key_init(); //key按键初始化
exter_inter_init(); //Key0中断初始化
epit1_init(0, 66000000/2); //EPIT1定时器初始化
while(1);
return 0;
}
经过测试,LED灯第一次亮的时间比后面的长。代码存在问题,经过检查发现,问题出现在 Led 初始化接口中。将 led_init()函数中 LED 灯关闭即可。
bsp_led.c 中LED 初始化接口代码如下:
//Led初始化
void led_init(void)
{
//复用为GPIO功能
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0);
//配置电气特性
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0X1070);
//配置为输出
GPIO1->GDIR = 0X08;
//关闭Led
GPIO1->DR |= (1 << 3);
}
以上就是裸机篇之的中断定时器 EPIT1 的实验。至此实验顺利完成。