目录
1.简介
通过上一个博客介绍的HAL库操作GPIO的函数,来实现蜂鸣器的的实验。笔者使用的开发板是STM32F103ZET6为MCU的正点原子精英板,读者可以使用自己的开发板来复现实验。开发板不是重点,重点是学习HAL库的使用。如果读者没学习过GPIO以及HAL库操作GPIO,可以通过下面的链接进行简单的学习一下:
2.蜂鸣器模块
蜂鸣器分为有源蜂鸣器和无源蜂鸣器两种,它们在结构、工作原理、驱动方式、声音特点和价格等方面存在明显的区别,下面展开介绍。
2.1有源蜂鸣器
有源蜂鸣器内部自带振荡源,将振荡电路等集成在蜂鸣器内部,只需给它通电就可以发声。
它的工作原理是基于压电效应或电磁效应工作。当接通直流电源后,内部的振荡电路产生一定频率的信号,驱动发声体振动发声。
有源蜂鸣器的驱动较为简单,只需提供合适的直流电源即可发声。电源的极性通常是固定的,接反可能无法正常工作。由于内部振荡源的频率固定,所以发出的声音频率单一、音调固定,通常为持续的单音,如“滴、滴”声。
由于有源蜂鸣器内部集成了振荡电路,其制造成本相对较高,价格通常比无源蜂鸣器贵一些。常用于对声音效果要求不高,只需要简单提示音的场合,如计算机、打印机、报警器等设备的状态提示。
2.2无源蜂鸣器
无源蜂鸣器内部没有振荡源,只有发声装置,需要外部提供一定频率的脉冲信号才能发声。
它也同样基于压电或电磁原理,但需要外部电路提供特定频率的交流电信号。当交流信号的频率与蜂鸣器的固有频率接近时,蜂鸣器发生共振,从而发出声音。
但是驱动相对复杂,需要使用信号发生器或微控制器(如 Arduino、单片机等)产生特定频率和占空比的脉冲信号来驱动。可以通过改变脉冲信号的频率和占空比来控制蜂鸣器发出不同音调、节奏的声音。
特点是可以通过调整输入信号的频率,发出不同音调的声音,还能模拟出多种复杂的声音效果,如音乐、警笛声等。
无源蜂鸣器的结构简单,成本较低,价格更为便宜,在对成本敏感的大规模应用中具有优势。适用于需要发出不同音调、模拟各种声音的场景,如电子玩具、门铃、智能家电的语音提示等。
3.硬件连接
笔者使用的正点原子的STM32F103ZE精英开发板上自带了一个有源蜂鸣器,连接在了PB8上,如下图所示:

从图中可以看出,PB8连接到一个名为Q1的晶体管的栅极(G)。当PB8输出高电平时,Q1导通,使得蜂鸣器(BEEP)的两端有电压差,从而发声;当PB8输出低电平时,Q1截止,蜂鸣器就不发出声音了。
4.编写代码
与上一章驱动LED的代码一样,首先要编写蜂鸣器初始化代码,然后编写打开蜂鸣器和关闭蜂鸣器代码,再编写蜂鸣器报警代码和检查蜂鸣器状态的代码。
4.1Beep.h编写
在.h文件中使用宏定义写出端口和引脚,为后续编程提高可读性,再使用枚举,写出Beep的两个状态,以及函数的声明。
比较简单,直接上代码:
#ifndef __BEEP_H__
#define __BEEP_H__
/*****************************************************
头文件
******************************************************/
#include "sys.h"
#include "delay.h"
/*****************************************************
宏定义
******************************************************/
#define BEEP_PORT GPIOB
#define BEEP_PIN GPIO_PIN_8
/*****************************************************
数据类型定义
******************************************************/
typedef enum
{
Beep_OFF = 0u,
Beep_ON = 1u
}Beep_State;
/*****************************************************
函数声明
******************************************************/
void Beep_Init(void);
void Beep_TurnOn(void);
void Beep_TurnOff(void);
void Beep_Alarm(unsigned char count);
Beep_State Beep_CheckStatus(void);
#endif
4.2蜂鸣器初始化代码
还是初始化GPIO,推挽输出模式,不使用上下拉,慢速,初始化PB8,再写入初始值即可。代码如下:
/**
* @brief Beep初始化函数
* @param 无
* @retval 无
*/
void Beep_Init(void)
{
/* 1.打开时钟 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/* 2.配置GPIO */
GPIO_InitTypeDef gpio_initure = {0};
gpio_initure.Pin = BEEP_PIN; //Beep引脚
gpio_initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
gpio_initure.Speed = GPIO_SPEED_FREQ_LOW; //慢速
gpio_initure.Pull = GPIO_NOPULL; //不使用上下拉电阻,推挽输出模式下,上下拉电阻通常无实际作用
HAL_GPIO_Init(BEEP_PORT, &gpio_initure); //调用GPIO初始化函数
/* 3.写入初始值,默认关闭 */
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
}
4.3蜂鸣器的打开和关闭
PB8输出高电平时,蜂鸣器就响;输出低电平时,蜂鸣器就不响。根据这一点,编写两个函数,即蜂鸣器的打开和关闭。代码如下:
/**
* @brief 打开蜂鸣器
* @param 无
* @retval 无
*/
void Beep_TurnOn(void)
{
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_SET);
}
/**
* @brief 关闭蜂鸣器
* @param 无
* @retval 无
*/
void Beep_TurnOff(void)
{
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
}
4.4蜂鸣器报警
再编写一个函数,我们传递一个无符号字符型参数,传递的数值是几,蜂鸣器就报警几次,发出滴滴滴的声音。如果传递的数值大于等于10,就按10次算,就滴10下。代码如下:
/**
* @brief 蜂鸣器报警
* @param count:报警的次数,数值为小于等于10的整数
* @retval 无
*/
void Beep_Alarm(unsigned char count)
{
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
if(count >= 10)
{
count = 10;
}
for(int i = 0; i < count; i++)
{
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_SET);
delay_ms(100);
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
delay_ms(100);
}
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
}
4.5检查蜂鸣器的状态
再设计一个函数,每次调用之后,返回值就是蜂鸣器的工作状态,比如蜂鸣器正在发出声音,此时我们调用该函数之后,得到的返回值就是Beep_ON。代码如下:
/**
* @brief 查询蜂鸣器状态
* @param 无
* @retval Beep_State,Beep_OFF为关闭状态,Beep_ON为开启状态
*/
Beep_State Beep_CheckStatus(void)
{
GPIO_PinState bitstatus = (GPIO_PinState)0;
Beep_State status = Beep_OFF;
bitstatus = HAL_GPIO_ReadPin(BEEP_PORT, BEEP_PIN);
if(bitstatus == GPIO_PIN_SET)
status = Beep_ON;
else if(bitstatus == GPIO_PIN_RESET)
status = Beep_OFF;
return status;
}
5.全部代码
笔者把整体的Beep.c、Beep.h和main.c放在下面,供读者参考。
5.1Beep.h
#ifndef __BEEP_H__
#define __BEEP_H__
/*****************************************************
头文件
******************************************************/
#include "sys.h"
#include "delay.h"
/*****************************************************
宏定义
******************************************************/
#define BEEP_PORT GPIOB
#define BEEP_PIN GPIO_PIN_8
/*****************************************************
数据类型定义
******************************************************/
typedef enum
{
Beep_OFF = 0u,
Beep_ON = 1u
}Beep_State;
/*****************************************************
函数声明
******************************************************/
void Beep_Init(void);
void Beep_TurnOn(void);
void Beep_TurnOff(void);
void Beep_Alarm(unsigned char count);
Beep_State Beep_CheckStatus(void);
#endif
5.2Beep.c
#include "Beep.h"
/**
* @brief Beep初始化函数
* @param 无
* @retval 无
*/
void Beep_Init(void)
{
/* 1.打开时钟 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/* 2.配置GPIO */
GPIO_InitTypeDef gpio_initure = {0};
gpio_initure.Pin = BEEP_PIN; //Beep引脚
gpio_initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
gpio_initure.Speed = GPIO_SPEED_FREQ_LOW; //慢速
gpio_initure.Pull = GPIO_NOPULL; //不使用上下拉电阻,推挽输出模式下,上下拉电阻通常无实际作用
HAL_GPIO_Init(BEEP_PORT, &gpio_initure); //调用GPIO初始化函数
/* 3.写入初始值,默认关闭 */
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
}
/**
* @brief 打开蜂鸣器
* @param 无
* @retval 无
*/
void Beep_TurnOn(void)
{
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_SET);
}
/**
* @brief 关闭蜂鸣器
* @param 无
* @retval 无
*/
void Beep_TurnOff(void)
{
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
}
/**
* @brief 蜂鸣器报警
* @param count:报警的次数,数值为小于等于10的整数
* @retval 无
*/
void Beep_Alarm(unsigned char count)
{
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
if(count >= 10)
{
count = 10;
}
for(int i = 0; i < count; i++)
{
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_SET);
delay_ms(100);
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
delay_ms(100);
}
HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET);
}
/**
* @brief 查询蜂鸣器状态
* @param 无
* @retval Beep_State,Beep_OFF为关闭状态,Beep_ON为开启状态
*/
Beep_State Beep_CheckStatus(void)
{
GPIO_PinState bitstatus = (GPIO_PinState)0;
Beep_State status = Beep_OFF;
bitstatus = HAL_GPIO_ReadPin(BEEP_PORT, BEEP_PIN);
if(bitstatus == GPIO_PIN_SET)
status = Beep_ON;
else if(bitstatus == GPIO_PIN_RESET)
status = Beep_OFF;
return status;
}
5.3main.c
#include "sys.h"
#include "uart1.h"
#include "delay.h"
#include "Beep.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
uart1_init(115200);
Beep_Init();
while(1)
{
// Beep_Alarm(5);
// delay_s(5);
Beep_TurnOn();
delay_ms(200);
Beep_TurnOff();
delay_s(2);
}
}

1140

被折叠的 条评论
为什么被折叠?



