linux键盘设置的文件在哪个文件夹,「正点原子Linux连载」第十五章按键输入试验...

原标题:「正点原子Linux连载」第十五章按键输入试验

第十五章按键输入试验

前面几章试验都是讲解如何使用I.MX6U的GPIO输出控制功能,I.MX6U的IO不仅能作为输出,而且也可以作为输入。I.MX6U-ALPHA开发板上有一个按键,按键连接了一个IO,将这个IO配置为输入功能,读取这个IO的值即可获取按键的状态(按下或松开)。本章通过这个按键来控制蜂鸣器的开关,通过本章的学习你将掌握如何将I.MX6UL的IO作为输入来使用。

15.1按键输入简介

按键就两个状态:按下或弹起,将按键连接到一个IO上,通过读取这个IO的值就知道按键是按下的还是弹起的。至于按键按下的时候是高电平还是低电平要根据实际电路来判断。前面几章我们都是讲解I.MX6U的GPIO作为输出使用,当GPIO连接按键的时候就要做为输入使用。关于I.MX6U的GPIO已经在第八章详细的讲解了,本章我们的主要工作就是配置按键所连接的IO为输入功能,然后读取这个IO的值来判断按键是否按下。

I.MX6U-ALPHA开发板上有一个按键KEY0,本章我们将会编写代码通过这个KEY0按键来控制开发板上的蜂鸣器,按一下KEY0蜂鸣器打开,再按一下蜂鸣器就关闭。

15.2 硬件原理分析

本试验我们用到的硬件有:

1) LED灯LED0。

2)蜂鸣器。

3)1个按键KEY0。

按键KEY0的原理图如图15.2.1所示:

8cdc2926105bc50c14414e39b560d432.png

图15.2.1 按键原理图

从图15.2.1可以看出,按键KEY0是连接到I.MX6U的UART1_CTS这个IO上的,KEY0接了一个10K的上拉电阻,因此KEY0没有按下的时候UART1_CTS应该是高电平,当KEY0按下以后UART1_CTS就是低电平。

15.3实验程序编写

本实验对应的例程路径为:开发板光盘-> 1、裸机例程->7_key。

本试验在上一章试验例程的基础上完成,重新创建VSCode工程,工作区名字为“key”,在工程目录的bsp文件夹中创建名为“key”和“gpio”两个文件夹。按键相关的驱动文件都放到“key”文件夹中,本章试验我们对GPIO的操作编写一个函数集合,也就是编写一个GPIO驱动文件,GPIO的驱动文件放到“gpio”文件夹里面。

新建bsp_gpio.c和bsp_gpio.h这两个文件,将这两个文件都保存到刚刚创建的bsp/gpio文件夹里面,然后在bsp_gpio.h文件夹里面输入如下内容:

示例代码15.3.1 bsp_gpio.h文件代码

1 #ifndef _BSP_GPIO_H

2 #define _BSP_GPIO_H

3 #define _BSP_KEY_H

4 #include "imx6ul.h"

5/***************************************************************

6 Copyright zuozhongkai Co., Ltd. 1998-2019. All rights reserved.

7文件名 : bsp_gpio.h

8作者 : 左忠凯

9版本 : V1.0

10描述 : GPIO操作文件头文件。

11其他 : 无

12论坛 : www.openedv.com

13日志 : 初版V1.0 2019/1/4 左忠凯创建

14 ***************************************************************/

15

16/* 枚举类型和结构体定义 */

17

typedef

enum _gpio_pin_direction

18

{

19 kGPIO_DigitalInput

=

0U

,

/* 输入 */

20 kGPIO_DigitalOutput

=

1U

,

/* 输出 */

21

}

gpio_pin_direction_t

;

22

23/* GPIO配置结构体 */

24

typedef

struct _gpio_pin_config

25

{

26 gpio_pin_direction_t direction

;

/* GPIO方向:输入还是输出 */

27uint8_t outputLogic

;

/* 如果是输出的话,默认输出电平 */

28

}

gpio_pin_config_t

;

29

30

31/* 函数声明 */

32void gpio_init

(

GPIO_Type

*

base

,

int pin

,

gpio_pin_config_t

*

config

);

33int gpio_pinread

(

GPIO_Type

*

base

,

int pin

);

34void gpio_pinwrite

(

GPIO_Type

*

base

,

int pin

,

int value

);

35

36 #endif

bsp_gpio.h中定义了一个枚举类型gpio_pin_direction_t和结构体gpio_pin_config_t,枚举类型gpio_pin_direction_t表示GPIO方向,输入或输出。结构体gpio_pin_config_t是GPIO的配置结构体,里面有GPIO的方向和默认输出电平两个成员变量。在bsp_gpio.c中输入如下所示内容:

示例代码15.3.2 bsp_gpio.c文件代码

1 #include "bsp_gpio.h"

2/***************************************************************

3 Copyright zuozhongkai Co., Ltd. 1998-2019. All rights reserved.

4文件名 : bsp_gpio.h

5作者 : 左忠凯

6版本 : V1.0

7描述 : GPIO操作文件。

8其他 : 无

9论坛 : www.openedv.com

10日志 : 初版V1.0 2019/1/4 左忠凯创建

11 ***************************************************************/

12

13/*

14 * @description : GPIO初始化。

15 * @param - base : 要初始化的GPIO组。

16 * @param - pin : 要初始化GPIO在组内的编号。

17 * @param - config : GPIO配置结构体。

18 * @return : 无

19 */

20void gpio_init

(

GPIO_Type

*

base

,

int pin

,

gpio_pin_config_t

*

config

)

21

{

22

if(

config

->

direction

==

kGPIO_DigitalInput

)

/* 输入 */

23

{

24 base

->

GDIR

&=~(

1

<<

pin

);

25

}

26

else

/* 输出 */

27

{

28 base

->

GDIR

|=

1

<<

pin

;

29 gpio_pinwrite

(

base

,

pin

,

config

->

outputLogic

);

/* 默认输出电平 */

30

}

31

}

32

33/*

34 * @description : 读取指定GPIO的电平值。

35 * @param – base : 要读取的GPIO组。

36 * @param - pin : 要读取的GPIO脚号。

37 * @return : 无

38 */

39int gpio_pinread

(

GPIO_Type

*

base

,

int pin

)

40

{

41

return(((

base

->

DR

)>>

pin

)&

0x1

);

42

}

43

44/*

45 * @description : 指定GPIO输出高或者低电平。

46 * @param – base : 要输出的的GPIO组。

47 * @param - pin : 要输出的GPIO脚号。

48 * @param – value : 要输出的电平,1 输出高电平, 0 输出低低电平

49 * @return : 无

50 */

51void gpio_pinwrite

(

GPIO_Type

*

base

,

int pin

,

int value

)

52

{

53

if(

value

==

0U

)

54

{

55 base

->

DR

&=~(

1U

<<

pin

);

/* 输出低电平 */

56

}

57

else

58

{

59 base

->

DR

|=(

1U

<<

pin

);

/* 输出高电平 */

60

}

61

}

文件bsp_gpio.c中有三个函数:gpio_init、gpio_pinread和gpio_pinwrite,函数gpio_init用于初始化指定的GPIO引脚,最终配置的是GDIR寄存器,此函数有三个参数,这三个参数的含义如下:

base:

要初始化的GPIO所属于的GPIO组,比如GPIO1_IO18就属于GPIO1组。

pin:

要初始化GPIO在组内的标号,比如GPIO1_IO18在组内的编号就是18。

config:

要初始化的GPIO配置结构体,用来指定GPIO配置为输出还是输入。

函数gpio_pinread是读取指定的GPIO值,也就是读取DR寄存器的指定位,此函数有两个参数和一个返回值,参数含义如下:

base:

要读取的GPIO所属于的GPIO组,比如GPIO1_IO18就属于GPIO1组。

pin:

要读取的GPIO在组内的标号,比如GPIO1_IO18在组内的编号就是18。

返回值:

读取到的GPIO值,为0或者1。

函数gpio_pinwrite是控制指定的GPIO引脚输入高电平(1)或者低电平(0),就是设置DR寄存器的指定位,此函数有三个参数,参数含义如下:

base:

要设置的GPIO所属于的GPIO组,比如GPIO1_IO18就属于GPIO1组。

pin:

要设置的GPIO在组内的标号,比如GPIO1_IO18在组内的编号就是18。

value:

要设置的值,1(高电平)或者0(低电平)。

我们以后就可以使用函数gpio_init设置指定GPIO为输入还是输出,使用函数gpio_pinread和gpio_pinwrite来读写指定的GPIO,文件bsp_gpio.c文件就讲解到这里。

接下来编写按键驱动文件,新建bsp_key.c和bsp_key.h这两个文件,将这两个文件都保存到刚刚创建的bsp/key文件夹里面,然后在bsp_key.h文件夹里面输入如下内容:

示例代码15.3.3 bsp_key.h文件代码

1 #ifndef _BSP_KEY_H

2 #define _BSP_KEY_H

3 #include "imx6ul.h"

4/***************************************************************

5 Copyright zuozhongkai Co., Ltd. 1998-2019. All rights reserved.

6文件名 : bsp_key.h

7作者 : 左忠凯

8版本 : V1.0

9描述 : 按键驱动头文件。

10其他 : 无

11论坛 : www.openedv.com

12日志 : 初版V1.0 2019/1/4 左忠凯创建

13 ***************************************************************/

14

15/* 定义按键值 */

16enum keyvalue

{

17 KEY_NONE

=

0

,

18 KEY0_VALUE

,

19

};

20

21/* 函数声明 */

22void key_init

(

void

);

23int key_getvalue

(

void

);

24

25 #endif

bsp_key.h文件中定义了一个枚举类型:keyvalue,此枚举类型表示按键值,因为I.MX6U-ALPHA开发板上只有一个按键,因此枚举类型里面只到KEY0_VALUE。在bsp_key.c中输入如下所示内容:

示例代码15.3.4 bsp_key.c文件代码

1 #include "bsp_key.h"

2 #include "bsp_gpio.h"

3 #include "bsp_delay.h"

4/***************************************************************

5 Copyright zuozhongkai Co., Ltd. 1998-2019. All rights reserved.

6文件名 : bsp_key.c

7作者 : 左忠凯

8版本 : V1.0

9描述 : 按键驱动文件。

10其他 : 无

11论坛 : www.openedv.com

12 日志 : 初版V1.0 2019/1/4 左忠凯创建

13 ***************************************************************/

14

15/*

16 * @description : 初始化按键

17 * @param : 无

18 * @return : 无

19 */

20void key_init

(

void

)

21

{

22 gpio_pin_config_t key_config

;

23

24 /* 1、初始化IO复用, 复用为GPIO1_IO18 */

25 IOMUXC_SetPinMux

(

IOMUXC_UART1_CTS_B_GPIO1_IO18

,

0

);

26

27 /* 2、、配置UART1_CTS_B的IO属性

28 *bit 16:0 HYS关闭

29 *bit [15:14]: 11 默认22K上拉

30 *bit [13]: 1 pull功能

31 *bit [12]: 1 pull/keeper使能

32 *bit [11]: 0 关闭开路输出

33 *bit [7:6]: 10 速度100Mhz

34 *bit [5:3]: 000 关闭输出

35 *bit [0]: 0 低转换率

36 */

37 IOMUXC_SetPinConfig

(

IOMUXC_UART1_CTS_B_GPIO1_IO18

,

0xF080

);

38

39 /* 3、初始化GPIO GPIO1_IO18设置为输入*/

40 key_config

.

direction

=

kGPIO_DigitalInput

;

41 gpio_init

(

GPIO1

,

18

,&

key_config

);

42

43

}

44

45 /*

46 * @description : 获取按键值

47 * @param : 无

48 * @return : 0 没有按键按下,其他值:对应的按键值

49 */

50int key_getvalue

(

void

)

51

{

52 int ret

=

0

;

53 staticunsignedchar release

=

1

;

/* 按键松开 */

54

55

if((

release

==

1

)&&(

gpio_pinread

(

GPIO1

,

18

)==

0

))

/* KEY0按下 */

56

{

57 delay

(

10

);

/* 延时消抖 */

58 release

=

0

;

/* 标记按键按下 */

59

if(

gpio_pinread

(

GPIO1

,

18

)==

0

)

60 ret

=

KEY0_VALUE

;

61

}

62

elseif(

gpio_pinread

(

GPIO1

,

18

)==

1

)

/* KEY0未按下 */

63

{

64 ret

=

0

;

65 release

=

1

;

/* 标记按键释放 */

66

}

67

68

return

ret

;

69

}

bsp_key.c中一共有两个函数:key_init和key_getvalue,key_init是按键初始化函数,用来初始化按键所使用的UART1_CTS这个IO。函数key_init先设置UART1_CTS复用为GPIO1_IO18,然后配置UART1_CTS这个IO为速度为100MHz,默认22K上拉。最后调用函数gpio_init来设置GPIO1_IO18为输入功能。

函数key_getvalue用于获取按键值,此函数没有参数,只有一个返回值,返回值表示按键值,返回值为0的话就表示没有按键按下,如果返回其他值的话就表示对应的按键按下了。获取按键值其实就是不断的读取GPIO1_IO18的值,如果按键按下的话相应的IO被拉低,那么GPIO1_IO18值就为0,如果按键未按下的话GPIO1_IO18的值就为1。此函数中静态局部变量release表示按键是否释放。

“示例代码15.3.4”中的57行是按键消抖延时函数,延时时间大约为10ms,用于消除按键抖动。理想型的按键电压变化过程如图15.3.1所示:

e4b82d5382d34e2a8b5bdf4436ba1e87.png

图15.3.1 理想的按键电压变化过程

在图15.3.1中,按键没有按下的时候按键值为1,当按键在t1时刻按键被按下以后按键值就变为0,这是最理想的状态。但是实际的按键是机械结构,加上刚按下去的一瞬间人手可能也有抖动,实际的按键电压变化过程如图15.3.2所示:

502b2e895a45bede0882cdbf9549c1c7.png

图15.3.2实际的按键电压变化过程

在图15.3.2中t1时刻按键被按下,但是由于抖动的原因,直到t2时刻才稳定下来,t1到t2这段时间就是抖动。一般这段时间就是十几ms左右,从图15.3.2中可以看出在抖动期间会有多次触发,如果不消除这段抖动的话软件就会误判,本来按键就按下了一次,结果软件读取IO值发现电平多次跳变以为按下了多次。所以我们需要跳过这段抖动时间再去读取按键的IO值,也就是至少要在t2时刻以后再去读IO值。在“示例代码15.3.4”中的57行是延时了大约10ms后再去读取GPIO1_IO18的IO值,如果此时按键的值依旧是0,那么就表示这是一次有效的按键触发。

按键驱动就讲解到这里,最后就是main.c文件的内容了,在main.c中输入如下代码:

示例代码15.3.5 main.c文件代码

/**************************************************************

Copyright zuozhongkai Co., Ltd. 1998-2019. All rights reserved.

文件名 : mian.c

作者 : 左忠凯

版本 : V1.0

描述 : I.MX6U开发板裸机实验7 按键输入实验

其他 : 本实验主要学习如何配置I.MX6U的GPIO作为输入来使用,通过

开发板上的按键控制蜂鸣器的开关。

论坛 : www.openedv.com

日志 : 初版V1.0 2019/1/4 左忠凯创建

**************************************************************/

1 #include "bsp_clk.h"

2 #include "bsp_delay.h"

3 #include "bsp_led.h"

4 #include "bsp_beep.h"

5 #include "bsp_key.h"

6

7/*

8 * @description : main函数

9 * @param : 无

10 * @return : 无

11 */

12int main

(

void

)

13

{

14 int i

=

0

;

15 int keyvalue

=

0

;

16 unsignedchar led_state

=

OFF

;

17 unsignedchar beep_state

=

OFF

;

18

19 clk_enable

();

/* 使能所有的时钟 */

20 led_init

();

/* 初始化led */

21 beep_init

();

/* 初始化beep */

22 key_init

();

/* 初始化key */

23

24

while(

1

)

25

{

26 keyvalue

=

key_getvalue

();

27

if(

keyvalue

)

28

{

29

switch(

keyvalue

)

30

{

31

case

KEY0_VALUE

:

32 beep_state

=!

beep_state

;

33 beep_switch

(

beep_state

);

34

break;

35

}

36

}

37 i

++;

38

if(

i

==

50

)

39

{

40 i

=

0

;

41 led_state

=!

led_state

;

42 led_switch

(

LED0

,

led_state

);

43

}

44 delay

(

10

);

45

}

46

return

0

;

47

}

main.c函数先初始化led灯、蜂鸣器和按键,然后在while(1)循环中不断的调用函数key_getvalue来读取按键值,如果KEY0按下的话就打开/关闭蜂鸣器。LED0作为系统提示指示灯闪烁,闪烁周期大约为500ms。本章例程的软件编写就到这里结束了,接下来就是编译下载验证了。

15.4编译下载验证

15.4.1编写Makefile和链接脚本

Makefile使用第十三章编写的通用Makefile,修改变量TARGET为key,在变量INCDIRS和SRCDIRS中追加“bsp/gpio”和“bsp/key”,修改完成以后如下所示:

示例代码15.4.1.1 Makefile文件代码

1 CROSS_COMPILE ?

=

arm-linux-gnueabihf-

2 TARGET ?

=

key

3

4/* 省略掉其它代码...... */

5

6 INCDIRS

:=

imx6ul \

7 bsp/clk \

8 bsp/led \

9 bsp/delay \

10 bsp/beep \

11 bsp/gpio \

12 bsp/key

13

14 SRCDIRS

:=

project \

15 bsp/clk \

16 bsp/led \

17 bsp/delay \

18 bsp/beep \

19 bsp/gpio \

20 bsp/key

21

22/* 省略掉其它代码...... */

23

24 clean

:

25 rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS)$(SOBJS)

第2行修改变量TARGET为“key”,也就是目标名称为“key”。

第11、12行在变量INCDIRS中添加GPIO和按键驱动头文件(.h)路径。

第19、20行在变量SRCDIRS中添加GPIO和按键驱动文件(.c)路径。

链接脚本就使用第十三章试验中的链接脚本文件imx6ul.lds即可。

15.4.2编译下载

使用Make命令编译代码,编译成功以后使用软件imxdownload将编译完成的key.bin文件下载到SD卡中,命令如下:

chmod 777 imxdownload //给予imxdownload可执行权限,一次即可

./imxdownload key.bin /dev/sdd //烧写到SD卡中

烧写成功以后将SD卡插到开发板的SD卡槽中,然后复位开发板。如果代码运行正常的话LED0会以大约500ms周期闪烁,按下开发板上的KEY0按键,蜂鸣器打开,再按下KEY0按键,蜂鸣器关闭。

责任编辑:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值