开发环境

Ubuntu
正点原子Linuxmini开发板
IMX6U芯片
Cortex-A7内核

硬件原理图

image.png
可实现按下按键,蜂鸣器发出声音,再按下按键关闭

程序编写

为方便配置GPIO的读写功能,添加了bsp_gpio
bsp_gpio.h

  1. #ifndef _BSP_GPIO_H
  2. #define _BSP_GPIO_H
  3. #define _BSP_KEY_H
  4. #include "imx6ul.h"
  5. /* 枚举类型和结构体定义 */
  6. typedef enum _gpio_pin_direction
  7. {
  8. kGPIO_DigitalInput = 0U, /* 输入 */
  9. kGPIO_DigitalOutput = 1U, /* 输出 */
  10. } gpio_pin_direction_t;
  11. typedef struct _gpio_pin_config
  12. {
  13. gpio_pin_direction_t direction; /* GPIO方向:输入还是输出 */
  14. uint8_t outputLogic; /* 如果是输出的话,默认输出电平 */
  15. } gpio_pin_config_t;
  16. /* 函数声明 */
  17. void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *config);
  18. int gpio_pinread(GPIO_Type *base, int pin);
  19. void gpio_pinwrite(GPIO_Type *base, int pin, int value);
  20. #endif

bsp_gpio.c

  1. #include "bsp_gpio.h"
  2. /*
  3. * @description : GPIO初始化。
  4. * @param - base : 要初始化的GPIO组。
  5. * @param - pin : 要初始化GPIO在组内的编号。
  6. * @param - config : GPIO配置结构体。
  7. * @return : 无
  8. */
  9. void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *config)
  10. {
  11. if(config->direction == kGPIO_DigitalInput) /* 输入 */
  12. {
  13. base->GDIR &= ~( 1 << pin);
  14. }
  15. else /* 输出 */
  16. {
  17. base->GDIR |= 1 << pin;
  18. gpio_pinwrite(base,pin, config->outputLogic);/* 设置默认输出电平 */
  19. }
  20. }
  21. /*
  22. * @description : 读取指定GPIO的电平值 。
  23. * @param - base : 要读取的GPIO组。
  24. * @param - pin : 要读取的GPIO脚号。
  25. * @return : 无
  26. */
  27. int gpio_pinread(GPIO_Type *base, int pin)
  28. {
  29. return (((base->DR) >> pin) & 0x1);
  30. }
  31. /*
  32. * @description : 指定GPIO输出高或者低电平 。
  33. * @param - base : 要输出的的GPIO组。
  34. * @param - pin : 要输出的GPIO脚号。
  35. * @param - value : 要输出的电平,1 输出高电平, 0 输出低低电平
  36. * @return : 无
  37. */
  38. void gpio_pinwrite(GPIO_Type *base, int pin, int value)
  39. {
  40. if (value == 0U)
  41. {
  42. base->DR &= ~(1U << pin); /* 输出低电平 */
  43. }
  44. else
  45. {
  46. base->DR |= (1U << pin); /* 输出高电平 */
  47. }
  48. }

按键驱动,会通过调用gpio的函数完配置引脚为读功能
bsp_key.h

  1. #ifndef _BSP_KEY_H
  2. #define _BSP_KEY_H
  3. #include "imx6ul.h"
  4. /* 定义按键值 */
  5. enum keyvalue{
  6. KEY_NONE = 0,
  7. KEY0_VALUE,
  8. KEY1_VALUE,
  9. KEY2_VALUE,
  10. };
  11. /* 函数声明 */
  12. void key_init(void);
  13. int key_getvalue(void);
  14. #endif

bsp_key.c

  1. #include "bsp_key.h"
  2. #include "bsp_gpio.h"
  3. #include "bsp_delay.h"
  4. /*
  5. * @description : 初始化按键
  6. * @param : 无
  7. * @return : 无
  8. */
  9. void key_init(void)
  10. {
  11. gpio_pin_config_t key_config;
  12. /* 1、初始化IO复用, 复用为GPIO1_IO18 */
  13. IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);
  14. IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);
  15. /* 3、初始化GPIO */
  16. //GPIO1->GDIR &= ~(1 << 18); /* GPIO1_IO18设置为输入 */
  17. key_config.direction = kGPIO_DigitalInput;
  18. gpio_init(GPIO1,18, &key_config);
  19. }
  20. /*
  21. * @description : 获取按键值
  22. * @param : 无
  23. * @return : 0 没有按键按下,其他值:对应的按键值
  24. */
  25. int key_getvalue(void)
  26. {
  27. int ret = 0;
  28. static unsigned char release = 1; /* 按键松开 */
  29. if((release==1)&&(gpio_pinread(GPIO1, 18) == 0)) /* KEY0 */
  30. {
  31. delay(10); /* 延时消抖 */
  32. release = 0; /* 标记按键按下 */
  33. if(gpio_pinread(GPIO1, 18) == 0)
  34. ret = KEY0_VALUE;
  35. }
  36. else if(gpio_pinread(GPIO1, 18) == 1)
  37. {
  38. ret = 0;
  39. release = 1; /* 标记按键释放 */
  40. }
  41. return ret;
  42. }

蜂鸣器驱动基本和LED驱动类似
bsp_beep.h

  1. #ifndef __BSP_BEEP_H
  2. #define __BSP_BEEP_H
  3. #include "imx6ul.h"
  4. /* 函数声明 */
  5. void beep_init(void);
  6. void beep_switch(int status);
  7. #endif

bsp_beep.c

  1. #include "bsp_beep.h"
  2. /*
  3. * @description : 初始化蜂鸣器对应的IO
  4. * @param : 无
  5. * @return : 无
  6. */
  7. void beep_init(void)
  8. {
  9. /* 1、初始化IO复用,复用为GPIO5_IO01 */
  10. IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0);
  11. IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0X10B0);
  12. /* 3、初始化GPIO,GPIO5_IO01设置为输出 */
  13. GPIO5->GDIR |= (1 << 1);
  14. /* 4、设置GPIO5_IO01输出高电平,关闭蜂鸣器 */
  15. GPIO5->DR |= (1 << 1);
  16. }
  17. /*
  18. * @description : 蜂鸣器控制函数,控制蜂鸣器打开还是关闭
  19. * @param - status : 0,关闭蜂鸣器,1 打开蜂鸣器
  20. * @return : 无
  21. */
  22. void beep_switch(int status)
  23. {
  24. if(status == ON)
  25. GPIO5->DR &= ~(1 << 1); /* 打开蜂鸣器 */
  26. else if(status == OFF)
  27. GPIO5->DR |= (1 << 1); /* 关闭蜂鸣器 */
  28. }

main.c

  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. * @description : main函数
  8. * @param : 无
  9. * @return : 无
  10. */
  11. int main(void)
  12. {
  13. int i = 0;
  14. int keyvalue = 0;
  15. unsigned char led_state = OFF;
  16. unsigned char beep_state = OFF;
  17. clk_enable(); /* 使能所有的时钟 */
  18. led_init(); /* 初始化led */
  19. beep_init(); /* 初始化beep */
  20. key_init(); /* 初始化key */
  21. while(1)
  22. {
  23. keyvalue = key_getvalue();
  24. //注意按键消抖
  25. if(keyvalue)
  26. {
  27. switch ((keyvalue))
  28. {
  29. case KEY0_VALUE:
  30. beep_state = !beep_state;
  31. beep_switch(beep_state);
  32. break;
  33. }
  34. }
  35. i++;
  36. if(i==50)
  37. {
  38. i = 0;
  39. led_state = !led_state;
  40. led_switch(LED0, led_state);
  41. }
  42. delay(10);
  43. }
  44. return 0;
  45. }

Makefile,内容基本没变,修改了目标名,添加了新加文件的路径

  1. CROSS_COMPILE ?= arm-linux-gnueabihf-
  2. TARGET ?= key
  3. CC := $(CROSS_COMPILE)gcc
  4. LD := $(CROSS_COMPILE)ld
  5. OBJCOPY := $(CROSS_COMPILE)objcopy
  6. OBJDUMP := $(CROSS_COMPILE)objdump
  7. INCDIRS := imx6ul \
  8. bsp/clk \
  9. bsp/led \
  10. bsp/delay \
  11. bsp/beep \
  12. bsp/gpio \
  13. bsp/key
  14. SRCDIRS := project \
  15. bsp/clk \
  16. bsp/led \
  17. bsp/delay \
  18. bsp/beep \
  19. bsp/gpio \
  20. bsp/key
  21. INCLUDE := $(patsubst %, -I %, $(INCDIRS))
  22. SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
  23. CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
  24. SFILENDIR := $(notdir $(SFILES))
  25. CFILENDIR := $(notdir $(CFILES))
  26. SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
  27. COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
  28. OBJS := $(SOBJS) $(COBJS)
  29. VPATH := $(SRCDIRS)
  30. .PHONY: clean
  31. $(TARGET).bin : $(OBJS)
  32. $(LD) -Timx6ul.lds -o $(TARGET).elf $^
  33. $(OBJCOPY) -O binary -S $(TARGET).elf $@
  34. $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis
  35. $(SOBJS) : obj/%.o : %.S
  36. $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<
  37. $(COBJS) : obj/%.o : %.c
  38. $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<
  39. clean:
  40. rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)

编译烧写同前面一样