在 I.MX6U-ALPHA 开发板上有一个有源蜂鸣器,通过 IO 输出高低电平即可控制蜂 鸣器的开关,本质上也属于 GPIO 的输出控制。
蜂鸣器常用于计算机、打印机、报警器、电子玩具等电子产品中,常用的蜂鸣器有两种: 有源蜂鸣器和无源蜂鸣器,这里的有“源”不是电源,而是震荡源,有源蜂鸣器内部带有震荡 源,所以有源蜂鸣器只要通电就会叫。无源蜂鸣器内部不带震荡源,直接用直流电是驱动不起 来的,需要 2K-5K 的方波去驱动。I.MX6U-ALPHA 开发板使用的是有源蜂鸣器,因此只要给其 供电就会工作,I.MX6U-ALPHA 开发板所使用的有源蜂鸣器如图 :
有源蜂鸣器只要通电就会叫,所以我们可以做一个供电电路, 这个供电电路可以由一个 IO来控制其通断,一般使用三极管来搭建这个电路。为什么我们不能像控制 LED 灯一样,直接将GPIO 接到蜂鸣器的负极,通过 IO 输出高低来控制蜂鸣器的通断。因为蜂鸣器工作的电流比LED 灯要大,直接将蜂鸣器接到 I.MX6U 的 GPIO 上有可能会烧毁 IO,所以我们需要通过一个三极管来间接的控制蜂鸣器的通断,相当于加了一层隔离。本章我们就驱动 I.MX6U-ALPHA 开发板上的有源蜂鸣器,使其周期性的“滴、滴、滴……”鸣叫
图中通过一个 PNP 型的三极管 8550 来驱动蜂鸣器,通过 SNVS_TAMPER1 这个 IO 来控制三极管 Q1 的导通,当 SNVS_TAMPER1 输出低电平的时候 Q1 导通,相当于蜂鸣器的正 极连接到 DCDC_3V3,蜂鸣器形成一个通路,因此蜂鸣器会鸣叫。同理,当 SNVS_TAMPER1 输出高电平的时候 Q2 不导通,那么蜂鸣器就没有形成一个通路,因此蜂鸣器也就不会鸣叫。
本实验在上一次(BSP实验)实验的基础上再做修改,把BSP实验的工程文件复制一份,
*bit 16:0 HYS 关闭
*bit [15:14]: 00 默认下拉
*bit [13]: 0 kepper 功能
*bit [12]: 1 pull/keeper 使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度 100Mhz
*bit [5:3]: 110 R0/6 驱动能力
*bit [0]: 0 低转换率
新建 beep.h 文件,保存到 bsp/beep 文件夹里面,在 beep.h 里面输入如下内容:
#ifndef BSP_BEEP_H
#define BSP_BEEP_H
#include "imx6ul.h"
void beep_init(void);
void bepp_switch(int status);
#endif // BSP_BEEP_H
beep_c文件
#include "bsp_beep.h"
/* BEEP初始化*/
void beep_init(void)
{
IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01, 0);
IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0x10b0);
/*GPIO初始化*/
GPIO5->GDIR |= (1 << 1); /*设置为输出*/
GPIO5->DR |= (1 << 1); /*默认关闭*/
}
/*蜂鸣器控制函数*/
void bepp_switch(int status)
{
if(status==ON)
GPIO5->DR &=~(1 << 1); /*低电平响*/
else if(status==OFF)
GPIO5->DR |= (1 << 1); /*高电平不响*/
}
beep.c 文件一共有两个函数: beep_init 和 beep_switch,其中 beep_init 用来初始化 BEEP 所使用的 GPIO,也就是 SNVS_TAMPER1,将其复用为 GPIO5_IO01,和上一章的 LED 灯初始化函数一样。 beep_switch 函数用来控制 BEEP 的开关,也就是设置 GPIO5_IO01 的高低电平,很简单。
把头文件包含进main.h中
#include "mian.h"
#include "bsp_clk.h"
#include "bsp_led.h"
#include "bsp_delay.h"
#include "bsp_beep.h"
int main(void)
{
clk_enable(); /* 使能所有的时钟 */
led_init(); /* 初始化 led */
beep_init(); /* BEEP初始化*/
while (1)
{
led_off(); /* 关闭 LED */
bepp_switch(OFF);
delay(1000);
led_on(); /* 打开 LED */
bepp_switch(ON);
delay(1000);
}
return 0;
}
主要修改目标文件和头文件路径和源码路径
CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET ?= beep
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
SRCDIRS := project \
bsp/clk \
bsp/led \
bsp/delay \
bsp/beep
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)
这个脚本链接和上一篇文章用的一样
SECTIONS{
. = 0x87800000;
.text :
{
obj/start.o
*(.text)
}
.rodata ALIGN(4) : {*(.rodata*)}
.data ALIGN(4) : {*(.data)}
__bss_start = .;
.bss ALIGN(4) : {*(.bss) *(COMMON)}
__bss_end = .;
}
使用 Make 命令编译代码,编译成功以后使用软件 imxdownload 将编译完成的 beep.bin 文 件下载到 SD 卡中,命令如下:
chmod 777 imxdownload //给予 imxdownload 可执行权限,一次即可
./imxdownload beep.bin /dev/sdd //烧写到 SD 卡中
烧写成功以后将 SD 卡插到开发板的 SD 卡槽中,然后复位开发板。如果代码运行正常的 话 LED 灯亮的时候蜂鸣器鸣叫,当 LED 灯灭的时候蜂鸣器不鸣叫,周期大概为 1000ms 。