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
谢谢大家的支持!
祝大家早安,午安,晚安!