beep蜂鸣器实验,来告诉你模块化、工程化编程的好处!

beep蜂鸣器实验,来告诉你模块化、工程化编程的好处!

写在前面:

上接前面关于BSP的博文,在那篇博文里我们搭建起了一个‘麻雀虽小,五脏俱全’的工程框架,现在框架已经搭起来了,这样当你想添加新功能时,方便的一批。闲话少说,直接搞起来!

正文

1、第一步看图

肯定还是先看电路图,找到你要调用的IO口。(这里就不配图了,makedown编辑器搞起图片来太麻烦。)

2、第二步新建功能模块

bsp文件夹下直接新建一个beep的文件夹,蜂鸣器驱动文件我们都是要放到里面的。

3、第三步写驱动文件

在上一步建好的beep文件夹中,新建bsp_beep.h、bsp_beep.c

一定要记好了,.c和.h就是一堆CP,两个都是成对出现的,.c里面构造相关函数,.h文件来提供接口API,以供主函数调用。

bsp_beep.h代码如下:

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

比较简单,没什么可说的。

bsp_beep.c代码如下:

#include "bsp_beep.h"

/*初始化蜂鸣器IO*/
void beep_init(void)
{
    /*IO复用,复用为GPIO5_IO01*/
    IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0);

    /*配置IO属性*/
    IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0x10B0);

    /*初始化设置为输出*/
    GPIO5->GDIR |= (1 << 1);

    /*输出高带你平,关闭蜂鸣器*/
    GPIO5->DR |= (1 << 1);

}

/*蜂鸣器控制函数*/
void beep_switch(int status)
{
    if(status == ON)
        GPIO5->DR &= ~(1 << 1);//打开
    else if (status == OFF)
        GPIO5->DR |= (1 << 1);//关闭
}

要说难点的或者不好理解的地方还是这里:

  • GPIO5->GDIR |= (1 << 1);
  • GPIO5->DR |= (1 << 1);
  • GPIO5->DR &= ~(1 << 1);//打开
  • GPIO5->DR |= (1 << 1);//关闭

如果猛的一下你看不懂这是啥意思的话,不要着急,要一步一步来,回想一下你学过的结构体运算符方面的知识,都是不难的。

4、第四部编写main.c

main.c文件只需要稍微做些更改就好:

#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"

int main(void)
{
	clk_enable();		/* 使能所有的时钟 			*/
	led_init();			/* 初始化led 			*/
	beep_init();//初始化beep

	while(1)			/* 死循环 				*/

	{	
		led_switch(LED0,'ON');	/* 打开LED 			*/
		beep_switch(ON);	
		delay(500);		/* 延时500ms 			*/
		
		led_switch(LED0,'OFF');		/* 关闭LED 			*/
		beep_switch(OFF);
		delay(500);		/* 延时500ms 			*/

	}
	return 0;
}

加上头文件bsp_beep.h,还有beep的初始化函数beep_init(),还有直接调用控制beep的函数beep_switch()

5、第五步编写makefile文件

也是简单的修改一下就行了:

CROSS_COMPILE ?= arm-linux-gnueabihf-#这一行针对不同的编译器是可以进行更改的
TARGET		  ?= beep#这个目标名字也是,针对不同到历程也是要改的

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
#SRCDIRS 包含的是整个工程的所有.c 和.S 文件目录
SRCDIRS 	  := project \
				bsp/clk \
				bsp/led \
				bsp/delay\
				bsp/beep
#变量 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)

  • 修改目标的名称为“beep”
  • 在变量 INCDIRS 中添加蜂鸣器驱动头文件路径,也就是文件 beep.h 的路径
  • 在变量 SRCDIRS 中添加蜂鸣器驱动文件路劲,也就是文件 beep.c 的路径

5、第五步编译就完了

完整的工程文件,可以去我的码云仓库下载:
https://gitee.com/iron2222/linux-driver-development/tree/master/6_beep

谢谢大家的支持!

祝大家早安,午安,晚安!

上一篇:六.蜂鸣器驱动


下一篇:按键控制蜂鸣器