1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
GPIO输入驱动实验-按键控制
写在前面: 和beep实验一样,在已有的工程框架上加功能就行了,冲!!!1、bsp下新建key、gpio文件夹 首先我们先来搞一个gpio的操作集合函数,同样的来一对CP:bsp_gpio.h、bsp_gpio.c bsp_gpio.h代码如下: #ifndef _BSP_GPIO_h #define _BSP_GPIO_h #define _BSP_KEY_h #include "imx6ul.h" /*枚举类型和结构体定义*/ typedef enum _gpio_pin_direction { kGPIO_DigitalInput = 0U,//输入,加一个U表示该常数是无符号整形 kGPIO_DigitalOutput = 1U,//输入 }gpio_pin_direction_t; /*GPIO配置结构体*/ typedef struct _gpio_pin_config { gpio_pin_direction_t direction;//GPIO 方向:输入还是输出 uint8_t outputLogic;//如果输出到话,默认输出电平 }gpio_pin_config_t; /*函数声明*/ void gpio_init(GPIO_Type *base,int pin,gpio_pin_config_t *config); int gpio_pinread(GPIO_Type *base,int pin); void gpio_pinwrite(GPIO_Type *base,int pin,int value); #endif // !_BSP_GPIO_h C基础知识枚举和结构体。
#include "bsp_gpio.h" /*GPIO初始化*/ void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *config) { if(config->direction == kGPIO_DigitalInput)//输入 { base->GDIR &= ~(1 << pin); } else//输出 { base->GDIR |= (1 << pin); gpio_pinwrite(base, pin,config->outputLogic);//默认输出电平 } } /*读取指定GPIO的数值*/ int gpio_pinread(GPIO_Type *base, int pin) { return (((base->DR) >> pin) & 0x1); } /*指定GPIO输出高电平或者低电平*/ void gpio_pinwrite(GPIO_Type *base, int pin, int value) { if (value == 0U) { base->DR &= ~(1U << pin);//输出低电平 } else { base->DR |= (1U << pin);//输出高点平 } } gpio初始化gpio_init,用来初始化指定的GPIO引脚+配置GDIR寄存器
存器的指定位
2、bsp_key.c 和 bsp_key.h 因为要加一个按键的功能,所以当然不能少得了按键CP了。 bsp_key.h代码如下: #ifndef _BSP_KEY_H #define _BSP_KEY_H #include "imx6ul.h" /*定义按键值*/ enum keyvalue{ KEY_NONE = 0, KEY0_VALUE, }; /*函数声明*/ void key_init(void); int key_getvalue(void); #endif // !_BSP_KEY_H 在我进行后面的交叉编译时,曾发现下面一个问题,就是KEY0_VALUE的的初始化问题,其实这个时候KEY0_VALUE已经初始化为1了,不要问我为什么,我也不知道。 但我有一个推测,首先这是一个枚举类型,针对的是谁?是keyvalue,是针对keyvalue的枚举,都枚举了啥:KEY_NONE和KEY0_VALUE,当你主动给他赋值时它就有了值,你不给的时候,就默认为1。 bsp_key.c 代码如下: #include "bsp_key.h" #include "bsp_gpio.h" #include "bsp_delay.h" /*初始化按键*/ void key_init(void) { gpio_pin_config_t key_config; //IO复用,GPIO1_IO18 IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0); //配置IO属性 IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080); //GPIO1-18设置为输入 key_config.direction = kGPIO_DigitalInput; gpio_init(GPIO1,18, &key_config); } /*获取按键值*/ int key_getvalue(void) { int ret = 0; static unsigned char release = 1;//按键松开 if((release==1)&&(gpio_pinread(GPIO1,18) == 0)) { delay(10);//延时防抖 release = 0;//标记按键按下 if (gpio_pinread(GPIO1,18) == 0) ret = KEY0_VALUE; } else if (gpio_pinread(GPIO1,18) == 1) //KEY0未按下 { ret = 0; release = 1;//标记按键释放 } return ret; } 可能看的还是比较少,有点不适应结构体+位运算符的表示形式,每一次都要停下来好好的去分析一下,才能理解。 key_init 和 key_getvalue一共两个函数,其中key_getvalue是获取返回值。 这里面有一个按键消抖的操作,其实就是加个延时,然后在判断一下就行了,51还有STM32里面都有讲过。 3、main.c 直接上代码: #include "bsp_clk.h" #include "bsp_delay.h" #include "bsp_led.h" #include "bsp_beep.h" #include "bsp_key.h" int main(void) { int i = 0; int keyvalue = 0; unsigned char led_state = OFF; unsigned char beep_state = OFF; clk_enable(); /* 使能所有的时钟 */ led_init(); /* 初始化led */ beep_init();//初始化beep key_init(); //初始化key while(1) /* 死循环 */ { keyvalue = key_getvalue(); if (keyvalue) { switch (keyvalue) { case KEY0_VALUE: beep_state = !beep_state; beep_switch(beep_state); break; } } i++; if(i==50) { i = 0; led_state = !led_state; led_switch(LED0,led_state); } delay(10); } return 0; } 主函数就很简单了,就是调用之前准备好的各种函数,不过有一点要说一下: led_state = !led_state4、makefile CROSS_COMPILE ?= arm-linux-gnueabihf-#这一行针对不同的编译器是可以进行更改的 TARGET ?= key#这个目标名字也是,针对不同到历程也是要改的 CC := $(CROSS_COMPILE)gcc LD := $(CROSS_COMPILE)ld OBJCOPY := $(CROSS_COMPILE)objcopy OBJDUMP := $(CROSS_COMPILE)objdump #变量 INCDIRS 包含整个工程的.h 头文件目录,文件中的所有头文件目录都要添加到变量INCDIRS中 INCDIRS := imx6ul bsp/clk bsp/led bsp/delay bsp/beep bsp/gpio bsp/key #SRCDIRS 包含的是整个工程的所有.c 和.S 文件目录 SRCDIRS := project bsp/clk bsp/led bsp/delay bsp/beep bsp/gpio bsp/key #变量 INCLUDE 使用到了函数 patsubst,通过函数 patsubst 给变量 INCDIRS 添加一个“-I”,因为 Makefile 语法要求指明头文件目录的时候需要加上“-I” INCLUDE := $(patsubst %, -I %, $(INCDIRS)) #变量 SFILES 保存工程中所有的.s 汇编文件(包含绝对路径),变量 SRCDIRS 已经存放了工程中所有的.c 和.S 文件,所以我们只需要从里面挑出所有的.S 汇编文件即可 SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S)) #变量 CFILES 和变量 SFILES 一样,只是 CFILES 保存工程中所有的.c 文件(包含绝对路径) CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c)) #使用函数 notdir 将 SFILES 和 CFILES 中的路径去掉 SFILENDIR := $(notdir $(SFILES)) CFILENDIR := $(notdir $(CFILES)) #默认所有的文件编译出来的.o 文件和源文件在同一个目录中 SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o)) COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o)) #变量 OBJS 是变量 SOBJS 和 COBJS 的集合 OBJS := $(SOBJS) $(COBJS) #VPATH 是指定搜索目录的,这里指定的搜素目录就是变量 SRCDIRS 所保存的目录,这样当编译的时候所需的.S 和.c 文件就会在 SRCDIRS 中指定的目录中查找 VPATH := $(SRCDIRS) .PHONY: clean $(TARGET).bin : $(OBJS) $(LD) -Timx6ul.lds -o $(TARGET).elf $^ $(OBJCOPY) -O binary -S $(TARGET).elf $@ $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis $(SOBJS) : obj/%.o : %.S $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $< $(COBJS) : obj/%.o : %.c $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $< clean: rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS) 还是改一下目标文件名字,还有驱动的头文件.h以及.c路径就可以了。 |
|
|
|
只有小组成员才能发言,加入小组>>
3316 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9060 浏览 16 评论
4088 浏览 18 评论
1180浏览 3评论
605浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
599浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2335浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1896浏览 2评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 03:02 , Processed in 1.115594 second(s), Total 78, Slave 59 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号