完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1)实验平台:正点原子Linux开发板 2)摘自《正点原子I.MX6U嵌入式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所示: 图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/* 枚举类型和结构体定义 */ 17typedefenum _gpio_pin_direction 18{ 19 kGPIO_DigitalInput =0U,/* 输入 */ 20 kGPIO_DigitalOutput =1U,/* 输出 */ 21} gpio_pin_direction_t; 22 23/* GPIO配置结构体 */ 24typedefstruct _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所示: 图15.3.1 理想的按键电压变化过程 在图15.3.1中,按键没有按下的时候按键值为1,当按键在t1时刻按键被按下以后按键值就变为0,这是最理想的状态。但是实际的按键是机械结构,加上刚按下去的一瞬间人手可能也有抖动,实际的按键电压变化过程如图15.3.2所示: 图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 return0; 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按键,蜂鸣器关闭。 |
|
相关推荐
|
|
1042 浏览 0 评论
IaaS+on+DPU(IoD)+下一代高性能算力底座技术白皮书
2035 浏览 0 评论
飞凌嵌入式-ELFBOARD 常用的USB接口及其不同版本介绍第1期
1074 浏览 0 评论
【Vision Board创客营连载体验】RA8D1-Vision Board上OSPI-Flash实践
1533 浏览 0 评论
I.MX6ULL-飞凌 ElfBoard ELF1板卡- 应用层更改引脚复用的方法
3755 浏览 0 评论
65237 浏览 21 评论
嵌入式热门DIY项目:智能机器人开源资料合集(原理图、代码、论文)
67782 浏览 22 评论
57821 浏览 32 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-18 06:21 , Processed in 0.607356 second(s), Total 60, Slave 44 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号