• 【正点原子STM32连载】第十四章 蜂鸣器实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1


    1)实验平台:正点原子MiniPro H750开发板
    2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560
    3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-336836-1-1.html
    4)对正点原子STM32感兴趣的同学可以加群讨论:879133275

    第十四章 蜂鸣器实验

    上一章,我们介绍了STM32H7的IO口作为输出的使用。本章,我们将通过另外一个例子继续讲述STM32H7的IO口作为输出的使用,不同的是本章讲的不是用IO口直接驱动器件,而是通过三极管间接驱动。我们将利用一个IO口来控制板载的有源蜂鸣器。
    本章分为如下几个小节:
    14.1 蜂鸣器简介
    14.2 硬件设计
    14.3 程序设计
    14.4 下载验证

    14.1 蜂鸣器简介

    蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
    MiniPRO STM32H750开发板板载的蜂鸣器是电磁式的有源蜂鸣器,如图14.1.1所示:
    在这里插入图片描述

    图14.1.1 有源蜂鸣器
    这里的有源不是指电源的 “源”,而是指有没有自带震荡电路,有源蜂鸣器自带了震荡电路,一通电就会发声;无源蜂鸣器则没有自带震荡电路,必须外部提供2~5Khz左右的方波驱动,才能发声。
    上一章,我们利用STM32的IO口直接驱动RGB灯,本章的蜂鸣器,我们能否直接用STM32的IO口驱动呢?让我们来分析一下:STM32H7的单个IO最大可以提供25mA电流(来自数据手册),而蜂鸣器的驱动电流是30mA左右,两者十分相近,但是全盘考虑,STM32H7整个芯片的电流,最大也就150mA,如果用IO口直接驱动蜂鸣器,其他地方用电就得省着点了,所以我们不用STM32H7的IO直接驱动蜂鸣器,而是通过三极管扩流后再驱动蜂鸣器,这样STM32H7的IO只需要提供不到1mA的电流就足够了。
    IO口使用虽然简单,但是和外部电路的匹配设计,还是要十分讲究的,考虑越多,设计就越可靠,可能出现的问题也就越少。

    14.2 硬件设计

    1. 例程功能
      蜂鸣器每隔300ms响或者停一次。LED0每隔300ms亮或者灭一次。LED0亮的时候蜂鸣器不叫,而LED0熄灭的时候,蜂鸣器叫。
    2. 硬件资源
      1)RGB灯
      LEDR : LED0 - PB4(红)
      2)蜂鸣器
      BEEP(PE4)
    3. 原理图
      蜂鸣器在硬件上是直接连接好了的,不需要经过任何设置,直接编写代码就可以了。蜂鸣器的驱动信号连接在STM32H7的PE4上。如图14.2.1所示:
      在这里插入图片描述

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

    14.3 程序设计

    本实验我们只是用到GPIO外设输出功能,关于HAL库的GPIO的API函数请看跑马灯实验的介绍。下面我们直接分析本实验的程序流程图。
    14.3.1 程序流程图
    在这里插入图片描述

    图14.3.1.1 蜂鸣器实验程序流程图
    14.3.2 程序解析

    1. 蜂鸣器驱动代码
      这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。蜂鸣器(BEEP)驱动源码包括两个文件:beep.c和beep.h。
      下面我们先解析beep.h的程序,我们把它分两部分功能进行讲解。
      由硬件设计小节,我们知道驱动蜂鸣器的三极管在硬件上连接到PE4,我们做了下面的引脚定义。
    /*****************************************************************************/
    /* 引脚 定义 */
    
    #define BEEP_GPIO_PORT                 GPIOE
    #define BEEP_GPIO_PIN                  GPIO_PIN_4
    /* PE口时钟使能 */
    #define BEEP_GPIO_CLK_ENABLE()       do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)
    /*****************************************************************************/
    可以看到这样定义跟跑马灯实验的是类似。
    为了后续对蜂鸣器进行便捷的操作,我们为蜂鸣器操作函数做了下面的定义。
    /* 蜂鸣器控制 */
    #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)
    
    /* 蜂鸣器取反控制 */
    #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_MEDIUM;  	/* 中速 */
        HAL_GPIO_Init(BEEP_GPIO_PORT, &gpio_init_struct); 	/* 初始化蜂鸣器引脚 */
    
        BEEP(0);                                                  	/* 关闭蜂鸣器 */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    对蜂鸣器的引脚设置为中速上拉的推挽输出。最后关闭关闭蜂鸣器,防止没有操作就响了。
    2. main.c代码
    在main.c里面编写如下代码:

    #include "./SYSTEM/sys/sys.h"
    #include "./SYSTEM/usart/usart.h"
    #include "./SYSTEM/delay/delay.h"
    #include "./BSP/LED/led.h"
    #include "./BSP/BEEP/beep.h"
    
    int main(void)
    {
        sys_cache_enable();                     	/* 打开L1-Cache */
        HAL_Init();                               	/* 初始化HAL库 */
        sys_stm32_clock_init(240, 2, 2, 4);  	/* 设置时钟, 480Mhz */
        delay_init(480);                         	/* 延时初始化 */
        led_init();                               	/* 初始化LED */
        beep_init();                              	/* 初始化蜂鸣器 */
    
        while (1)
        {
            LED0(0);
            BEEP(0);
            delay_ms(300);
            LED0(1);
            BEEP(1);
            delay_ms(300);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    首先是调用系统级别的初始化:sys_cache_enable函数使能I-Cache和D-Cache,然后初始化 HAL库、系统时钟和延时函数。接下来,调用led_init来初始化RGB灯,调用beep_init函数初始化蜂鸣器。最后在无限循环里面实现LED0和蜂鸣器间隔300ms交替闪烁和打开关闭一次。
    14.4 下载验证
    下载完之后,可以看到LED0亮的时候蜂鸣器不叫,而LED0熄灭的时候,蜂鸣器叫(因为他们的有效信号相反)。间隔为0.3秒左右,符合预期设计。
    至此,本章的学习就结束了。通过本章,我们进一步学习IO作为输出的使用方法,同时巩固了前面知识的学习。希望大家在开发板上实际验证一下,从而加深印象。

  • 相关阅读:
    4-2计算小于1000的正整数的平方根
    甲骨文真的要开放Java EE?
    package-info.java
    ImageKnife组件,让小白也能轻松搞定图片开发
    Linux进程
    常见的Java上机面试题
    web爬虫第二弹 chrome开发者工具
    java生态体系
    ARM开发初级-STM32F4寄存器-学习笔记03
    FreeSWITCH 1.10.10 简单图形化界面8 - 讯时FXO网关SIP注册公网IPPBX落地
  • 原文地址:https://blog.csdn.net/weixin_55796564/article/details/126466258