本实验的源码工程在开发板光盘资料的:i.MX6UL终结者光盘资料\04_裸机例程源码\10_key_filter 目录下。我们在Ubuntu系统下使用命令“mkdir 10_key_filter”建立“10_key_filter”文件夹,如图 1所示:
然后使用“cd 10_key_filter”命令进入到10_key_filter文件夹,如图 2所示:
然后使用命令“cp -r …/9_epit_timer/* ./”将上一章试验中的所有内容拷贝到刚刚新建的“10_key_filter”里面,如图 3所示:
然后在drivers目录下建立keyfilter文件夹,然后在“drivers/keyfilter”目录中新建keyfilter.h和keyfilter.c两个文件,然后在keyfilter.h文件输入下面的代码:
1 #ifndef _BSP_KEYFILTER_H
2 #define _BSP_KEYFILTER_H
3
4
5 /* 函数声明 */
6 void filterkey_init(void);
7 void filtertimer_init(unsigned int value);
8 void filtertimer_stop(void);
9 void filtertimer_restart(unsigned int value);
10 void filtertimer_irqhandler(void);
11 void gpio1_16_31_irqhandler(void);
12
13 #endif
在keyfilter.h文件中声明了一些函数,然后我们打开keyfilter.c文件,在里面输入下面的代码:
1 #include "key.h"
2 #include "gpio.h"
3 #include "int.h"
4 #include "beep.h"
5 #include "keyfilter.h"
6
7 /*
8 * @description : 按键初始化
9 * @param : 无
10 * @return : 无
11 */
12 void filterkey_init(void)
13 {
14 gpio_pin_config_t key_config;
15
16 /* 1、初始化IO复用 */
17 IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);
18
19 /* 2、、配置GPIO1_IO18的IO属性
20 *bit 16:0 HYS关闭
21 *bit [15:14]: 11 默认22K上拉
22 *bit [13]: 1 pull功能
23 *bit [12]: 1 pull/keeper使能
24 *bit [11]: 0 关闭开路输出
25 *bit [7:6]: 10 速度100Mhz
26 *bit [5:3]: 000 关闭输出
27 *bit [0]: 0 低转换率
28 */
29 IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);
30
31 /* 3、初始化GPIO为中断 */
32 key_config.direction = kGPIO_DigitalInput;
33 key_config.interruptMode = kGPIO_IntFallingEdge;
34 key_config.outputLogic = 1;
35 gpio_init(GPIO1, 18, &key_config);
36
37 GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); /*使能GIC中对应中断 */
38
39 /* 注册中断服务函数 */
40 system_register_irqhandler(GPIO1_Combined_16_31_IRQn,
41 (system_irq_handler_t)gpio1_16_31_irqhandler,
42 NULL);
43
44 gpio_enableint(GPIO1, 18); /* 使能GPIO1_IO18的中断功能 */
45
46 filtertimer_init(66000000/100); /* 初始化定时器,10ms */
47 }
48
49
50 /*
51 * @description : 初始化用于消抖的定时器,默认关闭定时器
52 * @param - value : 定时器EPIT计数值
53 * @return : 无
54 */
55 void filtertimer_init(unsigned int value)
56 {
57 EPIT1->CR = 0; //先清零
58
59 /*
60 * CR寄存器:
61 * bit25:24 01 时钟源选择Peripheral clock=66MHz
62 * bit15:4 0 1分频
63 * bit3: 1 当计数器到0的话从LR重新加载数值
64 * bit2: 1 比较中断使能
65 * bit1: 1 初始计数值来源于LR寄存器值
66 * bit0: 0 先关闭EPIT1
67 */
68 EPIT1->CR = (1<<24 | 1<<3 | 1<<2 | 1<<1);
69
70 /* 计数值 */
71 EPIT1->LR = value;
72
73 /* 比较寄存器,当计数器值和此寄存器值相等的话就会产生中断 */
74 EPIT1->CMPR = 0;
75
76 GIC_EnableIRQ(EPIT1_IRQn); /* 使能GIC中对应的中断 */
77
78 /* 注册中断服务函数 */
79 system_register_irqhandler(EPIT1_IRQn,
(system_irq_handler_t)filtertimer_irqhandler, NULL);
80 }
81
82 /*
83 * @description : 关闭定时器
84 * @param : 无
85 * @return : 无
86 */
87 void filtertimer_stop(void)
88 {
89 EPIT1->CR &= ~(1<<0); /* 关闭定时器 */
90 }
91
92 /*
93 * @description : 重启定时器
94 * @param - value : 定时器EPIT计数值
95 * @return : 无
96 */
97 void filtertimer_restart(unsigned int value)
98 {
99 EPIT1->CR &= ~(1<<0); /* 先关闭定时器 */
100 EPIT1->LR = value; /* 计数值 */
101 EPIT1->CR |= (1<<0); /* 打开定时器 */
102 }
103
104 /*
105 * @description : 定时器中断处理函数
106 * @param : 无
107 * @return : 无
108 */
109 void filtertimer_irqhandler(void)
110 {
111 static unsigned char state = OFF;
112
113 if(EPIT1->SR & (1<<0)) /* 判断比较事件是否发生 */
114 {
115 filtertimer_stop(); /* 关闭定时器 */
116 if(gpio_pinread(GPIO1, 18) == 0) /* KEY0 */
117 {
118 state = !state;
119 beep_switch(state); /* 反转蜂鸣器 */
120 }
121 }
122
123 EPIT1->SR |= 1<<0;/* 清除中断标志位 */
124 }
125
126 /*
127 * @description : GPIO中断处理函数
128 * @param : 无
129 * @return : 无
130 */
131 void gpio1_16_31_irqhandler(void)
132 {
133 /* 开启定时器 */
134 filtertimer_restart(66000000/100);
135
136 /* 清除中断标志位 */
137 gpio_clearintflags(GPIO1, 18);
138 }
keyfilter.c文件中一共有6个函数。
filterkey_init是初始化函数,初始化了按键使用的IO,设置这个IO的中断模式,然后注册中断处理函数并使能按键IO的中断,最后调用filtertimer_init函数,初始化EIPT1定时器。
filtertimer_init函数有一个参数value,他是指定时周期,我们这里传入的是66000000/100,相当于是10ms的定时周期,filtertimer_init函数的内容和上一章节的EPIT1定时器初始化一样。
filtertimer_stop函数是停止EPIT1定时器。
filtertimer_restart是重新启动EPIT1定时器。
filtertimer_irqhandler是EPIT1定时器的中断处理函数,在该函数里面如果我们读取到的按键状态是按下,那么就设置蜂鸣器的状态翻转。
gpio1_16_31_irqhandler是按键IO的中断处理函数,他的作用是检测到有按键按下就可以EPIT1定时器。
最后我们修改工程根目录下的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 "keyfilter.h"
8
9 /*
10 * @description : main函数
11 * @param : 无
12 * @return : 无
13 */
14 int main(void)
15 {
16 unsigned char state = OFF;
17
18 int_init(); /* 初始化中断(一定要最先调用!) */
19 imx6u_clkinit(); /* 初始化系统时钟 */
20 clk_enable(); /* 使能所有的时钟 */
21 led_init(); /* 初始化led */
22 beep_init(); /* 初始化beep */
23 filterkey_init(); /* 带有消抖功能的按键 */
24
25 while(1)
26 {
27 state = !state;
28 led_switch(LED0, state);
29 delay(500);
30 }
31
32 return 0;
33 }
main.c文件中第23行调用filterkey_init 函数,filterkey_init来初始化按键IO,注册按键中断处理函数,最后调用EPIT1定时器初始化函数,最后程序进入while(1)循环里面,在循环里面每隔500ms翻转一下LED的状态。