IMX6ULL之EPIT中断定时器实验说明二

一.    EPIT中断定时器

EPIT定时器:一种中断定时器。详细的介绍可以参考上一篇文章:

IMX6ULL裸机篇之按键中断实验_凌雪舞的博客-CSDN博客

本文学习一下 EPIT定时器的使用。实现如下功能:

实现 500ms 周期的定时器。

我们在 EPIT中断服务函数里,实现 LED灯亮灭。

二.   EPIT中断定时器实验

1.    EPIT中断定时器实验工作

(1)  设置 EPIT1 的时钟源,工作模式,时钟源选择,分频值,使能比较中断等。EPITx_CR 寄存器设置。

分频值与计数器加载值计算公式如下:

Tout = ((frac +1 )* value) / Tclk;
Tclk EPIT1 的输入时钟频率 ( 单位 Hz)
Tout EPIT1 的溢出时间 ( 单位 S)

(2)  EPIT1 中断设置

(3)  使能 GIC 中对应的 EPIT1 中断,注册中断服务函数。

如果需要,还可以设置中断优先级。

(4)  实现中断服务函数。
(5)  使能 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.  代码实现

bsp 文件夹下 创建名为" epittimer " 的文件夹,然后在该目录下创建 bsp_epittimer.c bsp_epittimer.h
bsp_epittimer.h 代码如下:
#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 的实验。至此实验顺利完成。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值