本实验的源码工程在开发板光盘资料的:i.MX6UL终结者光盘资料\04_裸机例程源码\9_epit_timer 目录下。我们在Ubuntu系统下使用命令“mkdir 9_epit_timer”建立“9_epit_timer”文件夹,图 1所示:
然后使用“cd 9_epit_timer”命令进入到9_epit_timer文件夹,如图 2所示:
然后使用命令“cp -r …/8_int/* ./”将上一章试验中的所有内容拷贝到刚刚新建的“9_epit_timer”里面,如图 3所示:
然后在drivers目录下建立epittimer文件夹,用来保存EPIT定时器的驱动文件,然后在“drivers/epittimer”目录中新建epittimer.h和epittimer.c两个文件,然后在epittimer.h文件输入下面的代码:
1 #ifndef _BSP_EPITTIMER_H
2 #define _BSP_EPITTIMER_H
3
4 #include "imx6ul.h"
5
6
7 /* 函数声明 */
8 void epit1_init(unsigned int frac, unsigned int value);
9 void epit1_irqhandler(void);
10
11 #endif
我们在epittimer.h文件中声明了两个函数,一个是EPIT1的初始化,另一个是中断处理函数。接下来我们打开epittimer.c文件,在里面输入下面的代码:
1 #include "epittimer.h"
2 #include "int.h"
3 #include "led.h"
4
5 /*
6 * @description : 初始化EPIT定时器.
7 * EPIT定时器是32位向下计数器,时钟源> 使用ipg=66Mhz
8 * @param - frac : 分频值,范围为0~4095,分别对应1~4096分频。
9 * @param - value : 倒计数值。
10 * @return : 无
11 */
12 void epit1_init(unsigned int frac, unsigned int value)
13 {
14 if(frac > 0XFFF)
15 frac = 0XFFF;
16
17 EPIT1->CR = 0; /* 先清零CR寄存器 */
18
19 /*
20 * CR寄存器:
21 * bit25:24 01 时钟源选择Peripheral clock=66MHz
22 * bit15:4 frac 分频值
23 * bit3: 1 当计数器到0的话从LR重新加载数值
24 * bit2: 1 比较中断使能
25 * bit1: 1 初始计数值来源于LR寄存器值
26 * bit0: 0 先关闭EPIT1
27 */
28 EPIT1->CR = (1<<24 | frac << 4 | 1<<3 | 1<<2 | 1<<1);
29
30 EPIT1->LR = value; /* 倒计数值 */
31 EPIT1->CMPR = 0; /* 比较寄存器*/
32
33 /* 使能GIC中对应的中断 */
34 GIC_EnableIRQ(EPIT1_IRQn);
35
36 /* 注册中断服务函数 */
37 system_register_irqhandler(EPIT1_IRQn, (system_irq_handler_t)epit1_irqhandler, NULL);
38
39 EPIT1->CR |= 1<<0; /* 使能EPIT1 */
40 }
41
42 /*
43 * @description : EPIT中断处理函数
44 * @param : 无
45 * @return : 无
46 */
47 void epit1_irqhandler(void)
48 {
49 static unsigned char state = 0;
50
51 state = !state;
52 if(EPIT1->SR & (1<<0)) /* 判断比较事件发生 */
53 {
54 led_switch(LED0, state); /* 定时器周期到,反转LED */
55 }
56
57 EPIT1->SR |= 1<<0; /* 清除中断标志位 */
58 }
epittimer.c文件我们定义了两个函数epit1_init(EPIT1初始化函数)和epit1_irqhandler(EPIT1中断处理函数)。
epit1_init函数有两个参数frac和value,frac是分频值,value是加载值。
第28行设置工作模式为set-and-forget,时钟源为66MHz。
第31行设置比较寄存器值为0(当计数器倒计到0的时候就会触发比较中断),所以分频值frac和加载值value决定了中断产生的频率,计算公式如下:
Tout = ((frac +1 )* value) / Tclk;
其中的Tclk是EPIT1的输入时钟频率,Tout是EPIT1的益出时间。如果我们现在要设置中断周期为500ms,可以设置分频值为0,(1分频),这样进入到EPIT1的时钟就是66MHz,那么500ms是1S的一半,即66000000/2=33000000,所以加载寄存器的值是33000000。
函数epit1_irqhandler是EPIT1的中断处理函数,进入此函数先读取EPIT1的SR寄存器的bit0判断是否是比较事件,如果是比较事件就翻转LED的状态,最后要写EPIT1的SR寄存器的bit0,清除中断标记。
然后我们修改main.c文件,在main.c里面输入下面的代码:
1 #include "clk.h"
2 #include "delay.h"
3 #include "led.h"
4 #include "beep.h"
5 #include "key.h"
6 #include "int.h"
7 #include "epittimer.h"
8
9 /*
10 * @description : main函数
11 * @param : 无
12 * @return : 无
13 */
14 int main(void)
15 {
16 int_init(); /* 初始化中断(一定要最先调用!) */
17 imx6u_clkinit(); /* 初始化系统时钟 */
18 clk_enable(); /* 使能所有的时钟 */
19 led_init(); /* 初始化led */
20 beep_init(); /* 初始化beep */
21 key_init(); /* 初始化key */
22 epit1_init(0, 66000000/2); /* 初始化EPIT1定时器,1分频
23 * 计数值为:66000000/2,也就是
24 * 定时周期为500ms。
25 */
26 while(1)
27 {
28 delay(500);
29 }
30
31 return 0;
32 }
在main.c里的main函数中第22行调用了epit1_init函数来初始化EPIT1定时器,frac为0(1分频),加载寄存器66000000/2,设置的定时周期为500ms,最后进入whil(1)循环里面
只是做下延时。