开发环境
Ubuntu
正点原子Linuxmini开发板
IMX6U芯片
Cortex-A7内核
硬件原理图
程序编写
为方便配置GPIO的读写功能,添加了bsp_gpio
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, /* 输入 */
kGPIO_DigitalOutput = 1U, /* 输出 */
} gpio_pin_direction_t;
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.c
#include "bsp_gpio.h"
/*
* @description : GPIO初始化。
* @param - base : 要初始化的GPIO组。
* @param - pin : 要初始化GPIO在组内的编号。
* @param - config : GPIO配置结构体。
* @return : 无
*/
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);/* 设置默认输出电平 */
}
}
/*
* @description : 读取指定GPIO的电平值 。
* @param - base : 要读取的GPIO组。
* @param - pin : 要读取的GPIO脚号。
* @return : 无
*/
int gpio_pinread(GPIO_Type *base, int pin)
{
return (((base->DR) >> pin) & 0x1);
}
/*
* @description : 指定GPIO输出高或者低电平 。
* @param - base : 要输出的的GPIO组。
* @param - pin : 要输出的GPIO脚号。
* @param - value : 要输出的电平,1 输出高电平, 0 输出低低电平
* @return : 无
*/
void gpio_pinwrite(GPIO_Type *base, int pin, int value)
{
if (value == 0U)
{
base->DR &= ~(1U << pin); /* 输出低电平 */
}
else
{
base->DR |= (1U << pin); /* 输出高电平 */
}
}
按键驱动,会通过调用gpio的函数完配置引脚为读功能
bsp_key.h
#ifndef _BSP_KEY_H
#define _BSP_KEY_H
#include "imx6ul.h"
/* 定义按键值 */
enum keyvalue{
KEY_NONE = 0,
KEY0_VALUE,
KEY1_VALUE,
KEY2_VALUE,
};
/* 函数声明 */
void key_init(void);
int key_getvalue(void);
#endif
bsp_key.c
#include "bsp_key.h"
#include "bsp_gpio.h"
#include "bsp_delay.h"
/*
* @description : 初始化按键
* @param : 无
* @return : 无
*/
void key_init(void)
{
gpio_pin_config_t key_config;
/* 1、初始化IO复用, 复用为GPIO1_IO18 */
IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);
IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);
/* 3、初始化GPIO */
//GPIO1->GDIR &= ~(1 << 18); /* GPIO1_IO18设置为输入 */
key_config.direction = kGPIO_DigitalInput;
gpio_init(GPIO1,18, &key_config);
}
/*
* @description : 获取按键值
* @param : 无
* @return : 0 没有按键按下,其他值:对应的按键值
*/
int key_getvalue(void)
{
int ret = 0;
static unsigned char release = 1; /* 按键松开 */
if((release==1)&&(gpio_pinread(GPIO1, 18) == 0)) /* KEY0 */
{
delay(10); /* 延时消抖 */
release = 0; /* 标记按键按下 */
if(gpio_pinread(GPIO1, 18) == 0)
ret = KEY0_VALUE;
}
else if(gpio_pinread(GPIO1, 18) == 1)
{
ret = 0;
release = 1; /* 标记按键释放 */
}
return ret;
}
蜂鸣器驱动基本和LED驱动类似
bsp_beep.h
#ifndef __BSP_BEEP_H
#define __BSP_BEEP_H
#include "imx6ul.h"
/* 函数声明 */
void beep_init(void);
void beep_switch(int status);
#endif
bsp_beep.c
#include "bsp_beep.h"
/*
* @description : 初始化蜂鸣器对应的IO
* @param : 无
* @return : 无
*/
void beep_init(void)
{
/* 1、初始化IO复用,复用为GPIO5_IO01 */
IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0);
IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0X10B0);
/* 3、初始化GPIO,GPIO5_IO01设置为输出 */
GPIO5->GDIR |= (1 << 1);
/* 4、设置GPIO5_IO01输出高电平,关闭蜂鸣器 */
GPIO5->DR |= (1 << 1);
}
/*
* @description : 蜂鸣器控制函数,控制蜂鸣器打开还是关闭
* @param - status : 0,关闭蜂鸣器,1 打开蜂鸣器
* @return : 无
*/
void beep_switch(int status)
{
if(status == ON)
GPIO5->DR &= ~(1 << 1); /* 打开蜂鸣器 */
else if(status == OFF)
GPIO5->DR |= (1 << 1); /* 关闭蜂鸣器 */
}
main.c
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_key.h"
/*
* @description : main函数
* @param : 无
* @return : 无
*/
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;
}
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 := imx6ul \
bsp/clk \
bsp/led \
bsp/delay \
bsp/beep \
bsp/gpio \
bsp/key
SRCDIRS := project \
bsp/clk \
bsp/led \
bsp/delay \
bsp/beep \
bsp/gpio \
bsp/key
INCLUDE := $(patsubst %, -I %, $(INCDIRS))
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES))
SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
OBJS := $(SOBJS) $(COBJS)
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)
编译烧写同前面一样