《STM32H7R7开发指南 V1.1 》第十三章 蜂鸣器实验

第十三章 蜂鸣器实验


       上一章,我们介绍了STM32的IO口作为输出的使用。本章,我们将通过另外一个例子继续讲述STM32的IO口作为输出的使用,不同的是本章讲的不是用IO口直接驱动器件,而是通过三极管间接驱动。我们将利用一个IO口来控制板载的有源蜂鸣器。

       本章分为如下几个小节:

       13.1 蜂鸣器简介

       13.2 硬件设计

       13.3 程序设计

       13.4 下载验证


        13.1 蜂鸣器简介

       蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。

       STM32H7R7开发板板载的蜂鸣器是电磁式的有源蜂鸣器,如图13.1.1所示:


图13.1.1 有源蜂鸣器


       这里的有源不是指电源的“源”,而是指有没有自带震荡电路,有源蜂鸣器自带了震荡电路,一通电就会发声;无源蜂鸣器则没有自带震荡电路,必须外部提供2~5Khz左右的方波驱动,才能发声。

       上一章,我们利用STM32的IO口直接驱动LED灯,本章的蜂鸣器,我们能否直接用STM32的IO口驱动呢?让我们来分析一下:STM32H7R7的单个IO最大可以提供20mA电流(来自数据手册),而蜂鸣器的驱动电流是30mA左右,两者十分相近,但是全盘考虑,STM32H7R7整个芯片的电流也是有限的,如果用IO口直接驱动蜂鸣器,其他地方用电就得省着点了,所以我们不用STM32H7R7的IO直接驱动蜂鸣器,而是通过三极管扩流后再驱动蜂鸣器,这样STM32H7R7的IO只需要提供不到1mA的电流就足够了。

       IO口使用虽然简单,但是和外部电路的匹配设计,还是要十分讲究的,考虑越多,设计就越可靠,可能出现的问题也就越少。


        13.2 硬件设计


       1. 例程功能

       蜂鸣器每隔500ms响或者停一次。LED0每隔500ms亮或者灭一次。LED0亮的时候蜂鸣器不叫,而LED0熄灭的时候,蜂鸣器叫。


       2. 硬件资源


       1)LED灯

              LED0– PD14


       2)蜂鸣器

              BEEP– PE5


       3. 原理图

       蜂鸣器在硬件上是直接连接好了的,不需要经过任何设置,直接编写代码就可以了。蜂鸣器的驱动信号连接在STM32H7R7的PE5上。如图13.2.1所示:


图13.2.1 蜂鸣器与STM32H7R7连接原理图


       我们用一个NPN三极管(S8050)来驱动蜂鸣器,R68主要用于防止蜂鸣器的误发声。驱动信号通过R66和R68间的电压获得,芯片上电时默认电平为低电平,故上电时蜂鸣器不会直接响起,当PE5输出高电平的时候,蜂鸣器将发声,当PE5输出低电平的时候,蜂鸣器停止发声。


        13.3 程序设计

       本实验我们只是用到GPIO外设输出功能,关于HAL库的GPIO的API函数请看跑马灯实验的介绍。


       13.3.1 程序解析


       1. 蜂鸣器驱动代码

       这里我们只讲解核心代码,详细的源码请大家光盘本实验对应源码。蜂鸣器(BEEP)驱动代码包括两个文件:beep.c和beep.h。

       下面我们先解析beep.h的程序,我们把它分两部分功能进行讲解。

       l   蜂鸣器引脚定义

       由硬件设计小节,我们知道驱动蜂鸣器的三极管在硬件上连接到PE5,类似跑马灯实验,我们做了下面的引脚定义。

/* 引脚 定义 */
#define BEEP_GPIO_PORT              GPIOE
#define BEEP_GPIO_PIN               GPIO_PIN_5
/* PE口时钟使能 */
#define BEEP_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOE_CLK_ENABLE();}while(0)


       l   蜂鸣器操作函数定义

       为了后续对蜂鸣器进行便捷的操作,我们为蜂鸣器操作函数做了下面的定义。

/* 蜂鸣器控制 */
#define BEEP(x)         do{ x ? \
          HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN, GPIO_PIN_SET) : \
          HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN, GPIO_PIN_RESET); \
                              }while(0)
/* BEEP状态翻转 */
#define BEEP_TOGGLE()   do{ HAL_GPIO_TogglePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN);\
    }while(0)     /* BEEP = !BEEP */

       BEEP(x)这个宏定义就是控制蜂鸣器的打开和关闭的。例如:如果要打开蜂鸣器,那么调用宏定义BEEP(1)即可,如果要关闭蜂鸣器,调用宏定义BEEP(0)即可。

       BEEP_TOGGLE()是控制蜂鸣器进行翻转的。这里也利用HAL_GPIO_TogglePin函数实现IO口输出电平取反操作。

       下面我们再解析beep.c的程序,这里只有一个函数beep_init,这是蜂鸣器的初始化函数,其定义如下:

/**
 * @brief       初始化BEEP相关IO口, 并使能时钟
 * @param       无
 * @retval      无
 */
void beep_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
BEEP_GPIO_CLK_ENABLE();                            /* BEEP时钟使能 */
 
    gpio_init_struct.Pin = BEEP_GPIO_PIN;              /* 蜂鸣器引脚 */
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;       /* 推挽输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;               /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;      /* 高速 */
HAL_GPIO_Init(BEEP_GPIO_PORT, &gpio_init_struct);  /* 初始化蜂鸣器引脚 */
    BEEP(0);                                           /* 关闭蜂鸣器 */
}

       对蜂鸣器的控制引脚模式设置为高速上拉的推挽输出。最后关闭关闭蜂鸣器,防止没有操作就响了。


       2. main.c代码

       在main.c里面编写如下代码:

int main(void)
{
    sys_mpu_config();                   /* 配置MPU */
    sys_cache_enable();                 /* 使能Cache */
    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(300, 6, 2);    /* 配置时钟,600MHz */
    delay_init(600);                    /* 初始化延时 */
    usart_init(115200);                 /* 初始化串口 */
    led_init();                         /* 初始化LED */
    beep_init();                        /* 初始化蜂鸣器 */
    
    while (1)
    {
        LED0(0);        /* 开启LED0 */
        BEEP(1);        /* 开启蜂鸣器 */
        delay_ms(500);  /* 延时500毫秒 */
        LED0(1);        /* 关闭LED0 */
        BEEP(0);        /* 关闭蜂鸣器 */
        delay_ms(500);  /* 延时500毫秒 */
    }
}

       首先初始化 HAL库、系统时钟和延时函数。接下来,调用led_init来初始化LED灯,调用beep_init函数初始化蜂鸣器。最后在无限循环里面实现LED0和蜂鸣器间隔500ms交替闪烁和打开关闭一次。


        13.4 下载验证

       下载完之后,可以看到LED0亮的时候蜂鸣器不叫,而LED0熄灭的时候,蜂鸣器叫(因为他们的有效信号相反)。间隔为0.5秒左右,符合预期设计。

       至此,本章的学习就结束了。通过本章,我们进一步学习IO作为输出的使用方法,同时巩固了前面知识的学习。希望大家在开发板上实际验证一下,从而加深印象。


请使用浏览器的分享功能分享到微信等