介绍
无源蜂鸣器(Piezo Buzzer),需外部方波驱动发声,体积小巧,适用于电子DIY、报警提示、玩具等场景。工作电压3~5V,谐振频率约2.3kHz,PCB直插式封装,音质清脆、功耗低。
无源蜂鸣器(Piezo Buzzer),需外部方波驱动发声,体积小巧,适用于电子DIY、报警提示、玩具等场景。工作电压3~5V,谐振频率约2.3kHz,PCB直插式封装,音质清脆、功耗低。
| 参数 | 值 |
|---|---|
| 直径 | 12mm |
| 类型 | 无源压电式蜂鸣器 |
| 高度 | 9.5mm |
| 声压级 | ≥85dB @10cm |
| 封装形式 | DIP直插 |
| 工作温度 | -20°C~+70°C |
| 工作电压 | 3~5V DC |
| 引脚间距 | 7.6mm |
| 线圈电阻 | 16Ω±4Ω |
| 谐振频率 | 2300±300Hz |
| 额定电流 | ≤30mA |
| 驱动方式 | 外部方波/PWM驱动 |
# 无源蜂鸣器驱动代码例程
## 硬件连接
| MCU引脚 | 连接 |
|---------|------|
| GPIO PA0 (TIM2_CH1) | → 1kΩ电阻 → S8050基极 |
| S8050集电极 | → 蜂鸣器(-) |
| 蜂鸣器(+) | → VCC (3.3V/5V) |
| S8050发射极 | → GND |
---
## 例程一:Arduino 环境
```cpp
/*
* 无源蜂鸣器 Arduino 驱动示例
* 硬件:GPIO 9 → 1kΩ → S8050基极 → 蜂鸣器
*/
#define BUZZER_PIN 9
// 音符频率定义 (Hz)
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_0 0 // 休止符
// 小星星旋律
int melody[] = {
NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4,
NOTE_A4, NOTE_A4, NOTE_G4,
NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4,
NOTE_D4, NOTE_D4, NOTE_C4,
NOTE_G4, NOTE_G4, NOTE_F4, NOTE_F4,
NOTE_E4, NOTE_E4, NOTE_D4,
NOTE_G4, NOTE_G4, NOTE_F4, NOTE_F4,
NOTE_E4, NOTE_E4, NOTE_D4,
NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4,
NOTE_A4, NOTE_A4, NOTE_G4,
NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4,
NOTE_D4, NOTE_D4, NOTE_C4
};
int noteDurations[] = {
4, 4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 4, 2,
4, 4, 4, 4, 4, 4, 2
};
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
Serial.begin(9600);
Serial.println("无源蜂鸣器测试开始");
}
void loop() {
// 播放小星星
for (int i = 0; i < sizeof(melody) / sizeof(melody[0]); i++) {
int noteDuration = 1000 / noteDurations[i];
if (melody[i] != NOTE_0) {
tone(BUZZER_PIN, melody[i], noteDuration);
}
delay(noteDuration * 1.3); // 音符间加间隔
noTone(BUZZER_PIN);
}
delay(2000); // 循环间隔
}
// ====== 驱动函数封装 ======
/**
* @brief 蜂鸣器发声
* @param frequency 频率(Hz),范围 31 ~ 65535
* @param duration_ms 持续时间(ms),0表示持续发声直到调用stopBuzzer()
*/
void buzzerBeep(uint16_t frequency, uint32_t duration_ms) {
if (frequency > 0) {
tone(BUZZER_PIN, frequency, duration_ms);
}
}
/**
* @brief 停止蜂鸣器
*/
void buzzerStop(void) {
noTone(BUZZER_PIN);
}
/**
* @brief 短促提示音
*/
void buzzerShortBeep(void) {
tone(BUZZER_PIN, 2300, 100);
}
/**
* @brief 报警音(交替频率)
*/
void buzzerAlarm(uint8_t repeat) {
for (uint8_t i = 0; i < repeat; i++) {
tone(BUZZER_PIN, 2000, 200);
delay(250);
tone(BUZZER_PIN, 3000, 200);
delay(250);
}
noTone(BUZZER_PIN);
}
```
---
## 例程二:STM32 HAL 库(PWM 方式)
```c
/*
* 无源蜂鸣器 STM32 HAL PWM 驱动
* 使用 TIM2_CH1 (PA0) 输出 PWM
* 系统时钟 72MHz,TIM2 预分频 72-1 → 1MHz
* ARR = 1000000/freq - 1
*/
#include "main.h"
#include <math.h>
// 音符频率定义
#define C4 262
#define D4 294
#define E4 330
#define F4 349
#define G4 392
#define A4 440
#define B4 494
#define C5 523
TIM_HandleTypeDef htim2;
static uint8_t buzzer_enabled = 0;
/**
* @brief 蜂鸣器PWM初始化
* @note PA0 = TIM2_CH1, 预分频72→1MHz计数
*/
void Buzzer_PWM_Init(void) {
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
htim2.Instance = TIM2;
htim2.Init.Prescaler = 72 - 1; // 72MHz / 72 = 1MHz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000 - 1; // 默认1kHz
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_PWM_Init(&htim2);
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 50%占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
}
/**
* @brief 设置蜂鸣器频率
* @param freq 频率(Hz),传0则停止
*/
void Buzzer_SetFrequency(uint16_t freq) {
if (freq == 0) {
HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
buzzer_enabled = 0;
return;
}
uint32_t arr = 1000000UL / freq - 1; // ARR = 1MHz/freq - 1
if (arr < 10) arr = 10;
if (arr > 65535) arr = 65535;
__HAL_TIM_SET_AUTORELOAD(&htim2, arr);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, arr / 2); // 50%占空比
if (!buzzer_enabled) {
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
buzzer_enabled = 1;
}
}
/**
* @brief 蜂鸣器发声指定时长(阻塞式)
* @param freq 频率(Hz)
* @param duration_ms 时长(ms)
*/
void Buzzer_Beep(uint16_t freq, uint32_t duration_ms) {
Buzzer_SetFrequency(freq);
HAL_Delay(duration_ms);
Buzzer_SetFrequency(0);
}
/**
* @brief 停止蜂鸣器
*/
void Buzzer_Stop(void) {
Buzzer_SetFrequency(0);
}
/**
* @brief 播放旋律(阻塞式)
* @param notes 音符频率数组
* @param durations 时值数组(如4=四分音符)
* @param length 数组长度
* @param tempo 速度(bpm)
*/
void Buzzer_PlayMelody(const uint16_t *notes, const uint8_t *durations,
uint8_t length, uint8_t tempo) {
for (uint8_t i = 0; i < length; i++) {
uint32_t note_ms = (60000UL / tempo) / durations[i];
if (notes[i] > 0) {
Buzzer_Beep(notes[i], note_ms * 0.9);
}
HAL_Delay(note_ms * 0.1); // 音符间隔
}
}
/* ====== 使用示例 ====== */
// 小星星旋律
const uint16_t twinkle_notes[] = {
C4, C4, G4, G4, A4, A4, G4, 0,
F4, F4, E4, E4, D4, D4, C4, 0
};
const uint8_t twinkle_durs[] = {
4, 4, 4, 4, 4, 4, 2, 8,
4, 4, 4, 4, 4, 4, 2, 8
};
int main(void) {
HAL_Init();
SystemClock_Config();
Buzzer_PWM_Init();
while (1) {
// 方式一:直接调用
Buzzer_Beep(2300, 200); // 2.3kHz 200ms
HAL_Delay(500);
// 方式二:播放旋律
Buzzer_PlayMelody(twinkle_notes, twinkle_durs, 16, 120);
HAL_Delay(2000);
}
}
```
---
## 例程三:ESP8266 (Arduino) 非阻塞驱动
```cpp
/*
* 无源蜂鸣器 ESP8266 非阻塞驱动
* 使用 Ticker 定时器实现非阻塞发声
* 硬件:GPIO D2 (GPIO4) → 1kΩ → S8050 → 蜂鸣器
*/
#include <Ticker.h>
#define BUZZER_PIN 4 // D2 = GPIO4
Ticker buzzerTicker;
volatile bool isPlaying = false;
void buzzerToggle() {
static uint8_t state = 0;
state = !state;
digitalWrite(BUZZER_PIN, state);
}
/**
* @brief 非阻塞蜂鸣器发声
* @param freq 频率(Hz)
* @param duration_ms 持续时间(ms)
*/
void buzzerBeepNonBlocking(uint16_t freq, uint32_t duration_ms) {
if (freq == 0 || duration_ms == 0) return;
// 计算Ticker间隔(微秒),频率=1/周期,周期/2=半周期(翻转间隔)
float period_us = 1000000.0f / freq;
float half_period_us = period_us / 2.0f;
isPlaying = true;
buzzerTicker.attach_us(half_period_us, buzzerToggle);
// 使用 once 在指定时间后停止
Ticker stopTicker;
stopTicker.once_ms(duration_ms, []() {
buzzerTicker.detach();
digitalWrite(BUZZER_PIN, LOW);
isPlaying = false;
});
}
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
Serial.begin(115200);
}
void loop() {
buzzerBeepNonBlocking(2300, 200);
delay(1000);
}
```
暂无参考文献