历史上的今天
返回首页

历史上的今天

今天是:2024年10月27日(星期日)

正在发生

2021年10月27日 | Linux之ARM(IMX6U)裸机C语言蜂鸣器驱动实验--驱动编写,编译

2021-10-27 来源:eefocus

前几篇博文试验中的驱动 LED 灯亮灭属于 GPIO 的输出控制,本章再巩固一下 I.MX6U 的 GPIO输出控制,在 I.MX6U-ALPHA 开发板上有一个有源蜂鸣器,通过 IO 输出高低电平即可控制蜂鸣器的开关,本质上也属于 GPIO 的输出控制


1、有源蜂鸣器简介

蜂鸣器常用于计算机、打印机、报警器、电子玩具等电子产品中,常用的蜂鸣器有两种:有源蜂鸣器和无源蜂鸣器,这里的有“源”不是电源,而是震荡源,有源蜂鸣器内部带有震荡源,所以有源蜂鸣器只要通电就会叫。无源蜂鸣器内部不带震荡源,直接用直流电是驱动不起来的,需要 2K-5K 的方波去驱动。 I.MX6U-ALPHA 开发板使用的是有源蜂鸣器,因此只要给其供电就会工作, I.MX6U-ALPHA 开发板所使用的有源蜂鸣器如图 14.2.1 所示:

有源蜂鸣器只要通电就会叫,所以我们可以做一个供电电路, 这个供电电路可以由一个 IO来控制其通断,一般使用三极管来搭建这个电路。为什么我们不能像控制 LED 灯一样,直接将GPIO 接到蜂鸣器的负极,通过 IO 输出高低来控制蜂鸣器的通断。因为蜂鸣器工作的电流比LED 灯要大,直接将蜂鸣器接到 I.MX6U 的 GPIO 上有可能会烧毁 IO,所以我们需要通过一个三极管来间接的控制蜂鸣器的通断,相当于加了一层隔离。本章我们就驱动 I.MX6U-ALPHA 开发板上的有源蜂鸣器,使其周期性的“滴、滴、滴……”鸣叫。


2、硬件原理分析

通过一个 PNP 型的三极管 8550 来驱动蜂鸣器,通过 SNVS_TAMPER1 这个 IO来控制三极管 Q1 的导通,当 SNVS_TAMPER1 输出低电平的时候 Q1 导通,相当于蜂鸣器的正极连接到 DCDC_3V3,蜂鸣器形成一个通路,因此蜂鸣器会鸣叫。同理,当 SNVS_TAMPER1输出高电平的时候 Q2 不导通,那么蜂鸣器就没有形成一个通路,因此蜂鸣器也就不会鸣叫。


3、实验程序的编写

本实验在上一次(BSP实验)实验的基础上再做修改,把BSP实验的工程文件复制一份,

新建 VSCode 工程,工程创建完成以后在 bsp 文件夹下新建名为“beep”的文件夹,蜂鸣器驱动文件都放到“beep”文件夹里面。


3.1、在写驱动之前要找到对应的寄存器设置好属性

3.11、复用为GPIO

再找到头文件中对应的宏

3.12、找到其设置电器属性并配置电器属性

*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 低转换率


3.2、beep.h

#ifndef __BEEP_H

#define __BEEP_H


#include "imx6ul.h"



void init_beep(void);

void beep_switch(int status);



#endif // !__BEEP_H


3.3、beep.c

#include "beep.h"


/*初始化蜂鸣器*/

void init_beep(void)

{


    IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0);  /*复用为GPIO*/


    /*

    *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 低转换率

    */

    IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0x10b0);/*设置其电器属性*/


    /*GPIO初始化*/

    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);

}


beep.c 文件一共有两个函数: beep_init 和 beep_switch,其中 beep_init 用来初始化 BEEP 所使用的 GPIO,也就是 SNVS_TAMPER1,将其复用为 GPIO5_IO01,和上一章的 LED 灯初始化函数一样。 beep_switch 函数用来控制 BEEP 的开关,也就是设置 GPIO5_IO01 的高低电平,很简单。


3.4、把头文件包含进main.h中

3.4.1、修改.vscode文件把beep文件夹路径加入到.vscode

3.4.2、修改main.h

3.5、调用驱动和蜂鸣器执行函数


main.c


#include "main.h"


int main() 

{

    clk_enable();  //使能外设时钟


    led_init(); //初始化LED


    init_beep();//初始化蜂鸣器

    

    while(1)

    {

        led_off();  

        beep_switch(OFF);

        delay(1000);


        led_on();

        beep_switch(ON);

        delay(1000);

    }


    return 0;

}


main.c中只有一个main函数, main函数先使能所有的外设时钟,然后初始化LED和BEEP。最终在 while(1)循环中周期性的开关 LED 灯和蜂鸣器,周期大约为 1000ms


4、编译下载和验证

4.1、修改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 := 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)


第 2 行修改目标的名称为“beep”。

第 10 行在变量 INCDIRS 中添加蜂鸣器驱动头文件路径,也就是文件 beep.h 的路径。

第 16 行在变量 SRCDIRS 中添加蜂鸣器驱动文件路劲,也就是文件 beep.c 的路径


4.2、编译下载

使用 Make 命令编译代码,编译成功以后使用软件 imxdownload 将编译完成的 beep.bin 文

件下载到 SD 卡中,命令如下:


chmod 777 imxdownload //给予 imxdownload 可执行权限,一次即可

./imxdownload beep.bin /dev/sdd //烧写到 SD 卡中


烧写成功以后将 SD 卡插到开发板的 SD 卡槽中,然后复位开发板。如果代码运行正常的话 LED 灯亮的时候蜂鸣器鸣叫,当 LED 灯灭的时候蜂鸣器不鸣叫,周期大概为 1000ms。

推荐阅读

史海拾趣

Crowd_Supply__Inc.公司的发展小趣事

在电子行业的众多初创公司中,Crowd Supply Inc.以其独特的理念和模式崭露头角。公司成立之初,便聚焦于开放式硬件和社区驱动的产品开发,这在当时的行业环境中还是一个较为新颖的概念。创始人团队由一群富有热情和创新精神的电子工程师和产品开发专家组成,他们通过线上平台汇聚了一群同样对电子硬件感兴趣的爱好者和开发者。初期,公司面临资金短缺、市场认可度低等挑战,但通过不断试错和社区反馈,逐渐找到了自己的发展方向。

圣邦微电子(Fangtek)公司的发展小趣事

Crowd Supply Inc.深知社区是其发展的核心动力。因此,公司不仅在产品开发上积极吸纳社区意见,还在市场推广、技术支持等方面与社区紧密合作。通过举办线上线下的技术交流活动、设立社区奖励机制等方式,公司成功吸引并留住了一批忠实的社区成员。这些成员不仅为公司带来了稳定的用户基础,还通过口碑传播扩大了公司的品牌影响力。

Electrolube公司的发展小趣事

在电子行业的激烈竞争中,Electrolube公司始终坚持以客户需求为导向,不断创新和拓展产品线。除了UVCL涂层外,公司还推出了一系列树脂、涂料和热管理解决方案的产品组合,为EV电池提供全面保护。

这些产品不仅具有优异的性能表现,而且能够满足不同客户的需求。例如,某些产品具有优异的耐高温性能,适用于高温环境下的电子设备;而另一些产品则具有出色的耐化学腐蚀性能,能够在恶劣的工作环境中保持稳定的性能。

Electrolube公司通过不断的技术创新和产品优化,成功拓展了市场份额,并在电子行业中树立了良好的品牌形象。同时,公司还积极与各大汽车制造商合作,共同推动电动汽车产业的发展。

Compostar Technology Co Ltd公司的发展小趣事

Compostar Technology Co Ltd公司自成立以来,一直致力于电子技术的研发与创新。在早期,公司凭借一款具有高效能耗比的电源管理芯片,成功打入了市场。随着技术的不断进步,公司逐渐将业务扩展到通信、智能家居和可穿戴设备等多个领域。公司不断投入研发资金,吸引了一批优秀的科研人才,成功研发出多款具有竞争力的产品,逐渐在电子行业中树立了良好的口碑。

CTC Coils Ltd公司的发展小趣事

随着国内市场的逐渐饱和,CTC Coils Ltd公司开始将目光投向海外市场。公司首先在欧洲设立了销售分支机构,通过参加国际电子展会、与当地企业建立合作关系等方式,逐步打开了欧洲市场。随后,公司又进一步拓展到北美和亚洲其他地区,实现了业务的国际化布局。

Futaba Electric Co Ltd公司的发展小趣事

随着国内市场的逐渐饱和,CTC Coils Ltd公司开始将目光投向海外市场。公司首先在欧洲设立了销售分支机构,通过参加国际电子展会、与当地企业建立合作关系等方式,逐步打开了欧洲市场。随后,公司又进一步拓展到北美和亚洲其他地区,实现了业务的国际化布局。

问答坊 | AI 解惑

最酷最全的电子类学习网站集锦

这是我在网上找的一些信息,是转载!希望对大家能有有用!希望大家多多支持! 由于字数太多,放在WORD文档中。…

查看全部问答>

TI2407入门资料

不知别人有没有上传过,也许对初学者有用 …

查看全部问答>

Xilinx 嵌入式平台套件产品简介(英文)

Embedded Design Challenges •  Rapidly changing product requirements and creating differentiated products •  Reducing total system cost and size •  Reducing hardware and software ...…

查看全部问答>

紧急!!SIM300DZ 模块对AT指令返回错误信息 在线等

我开发的平台是S3c2410,我想在嵌入式linux下实现GPRS上网,使用pppd call GPRS方式,SIM300DZ模块使用的是3脚串口,模块开机后向其拨打电话可以接通,但是执行pppd call GPRS,执行到send(AT)EXpect(OK)时,串口返回的是“%lee”这是怎么回事 ...…

查看全部问答>

电脑怎样连接到GPRS网络?

如题:电脑怎样连接到GPRS网络?…

查看全部问答>

####51单片机 4M晶振,如何实现1秒钟的精确定时?#####

初看,很简单,越研究越深入,发觉越麻烦。若换成12M 或者 6M的晶振,不叫问题,but,目前要求用89C51,晶振4M,实现1s的精确定时。 我们知道 对51单片机而言,一个机器周期等于12个晶振周期,故: 若晶振为12M,1个机器周期=12*(1/12M)=1us ...…

查看全部问答>

高分求解:嵌入式中一条奇怪的语句

GBLS    VBar VBar        SETS    \"|\" MACRO         START_REGION        $NameBegin         LCLS    TempName TempNa ...…

查看全部问答>

一个很邪门的问题

我帮别人做个读IO口,然后通过串口发出去的程序,用PC调试正常,怎么试怎么好,但是将单片机接到终端设备上去,终端收到的数据出错,但是如果将这个数据发给一台pc,单片机将数据发给pc,然后pc用相同的串口设置将收到数据发给设备,则设备接收数据 ...…

查看全部问答>

uart 接收发送新玩法

本帖最后由 jorya_txj 于 2014-1-5 20:18 编辑 很多时候,用户发送具体消息的时候,也需要发送一个消息长度。比如在网卡中断中接收到了一包数据,发送消息给外面任务的时候,也需要告诉外面的任务消息的长度是多少。使用之前的queue模块做需要一 ...…

查看全部问答>

【Rayeager PX2】PX2上使用GPIO口的例程

之前楼主在论坛中已经分享了简单驱动的编写,现在楼主再来教刚接触板子的新手们如何引用调用GPIO,不过这里楼主并没有将GPIO口的函数封装成库,然后在eclipse上调用,楼主这边的例子,只是简单的用adb工具进入板中,然后用一个测试程序使用端口,有 ...…

查看全部问答>