STM32F103驱动有源蜂鸣器+OLED显示状态完整教程(含三极管驱动电路讲解)
一、前言
很多刚入门 STM32 的同学做蜂鸣器实验时,会遇到蜂鸣器不响、常鸣、声音微弱、分不清有源 / 无源蜂鸣器的问题。本文基于 STM32F103C8T6,搭配高电平有效有源蜂鸣器模块+I2C OLED 显示屏,实现每隔 1 秒蜂鸣器鸣叫 / 停止切换,OLED 实时打印 GPIO 电平与蜂鸣器工作状态;同时补充三极管分立元件驱动电路原理,解决单片机 IO 口驱动能力不足、3.3V 控制 5V 负载电压衰减问题,硬件接线、原理、源码、实物调试全部讲透,新手可直接复刻。
实验实现效果
单片机 PA7 引脚周期性输出高低电平控制蜂鸣器,循环逻辑:
- PA7 输出高电平 → 蜂鸣器鸣叫 1s,OLED 显示 LEVEL:HIGH、BUZZER:ON
- PA7 输出低电平 → 蜂鸣器静音 1s,OLED 显示 LEVEL:LOW、BUZZER:OFF 无限循环切换,全程屏幕同步反馈引脚状态,直观观察 GPIO 输出逻辑。

二、硬件清单与接线说明
1. 所需器件
- STM32F103C8T6 最小系统板
- 有源蜂鸣器模块(高电平有效,带板载驱动)
- 0.96 寸 I2C OLED 显示屏
- S8050 NPN 三极管、1K 电阻 ×2、LED(拓展电路使用)
- 杜邦线若干、3.3V/5V 直流电源
2. 模块直连单片机简易接线(推荐新手)
适用于自带驱动电路的有源蜂鸣器模块,无需额外三极管,接线极简:
| 外设模块引脚 | STM32 引脚 | 功能说明 |
|---|---|---|
| 蜂鸣器 IN/S | PA7 | 蜂鸣器控制信号,高电平触发鸣叫 |
| 蜂鸣器 VCC | 3.3V/5V | 按模块丝印供电,3.3V 模块接 3.3V,5V 模块接 5V |
| 蜂鸣器 GND | 开发板 GND | 系统共地,必接! |
| OLED SCL | PB8 | I2C 时钟信号线 |
| OLED SDA | PB9 | I2C 数据信号线 |
| OLED VCC | 3.3V | OLED 供电,禁止接 5V 易烧屏 |
| OLED GND | 开发板 GND | 屏幕共地 |
重点:为什么所有模块必须共地?
STM32 单片机识别高低电平是以自身 GND 作为电压参考基准。如果蜂鸣器、OLED 不与单片机共地,IO 输出的 3.3V/0V 电平无法被模块正确识别,会出现蜂鸣器不发声、持续乱响、OLED 花屏、显示错乱等故障,接线时所有 GND 必须连在一起。

3. 拓展:S8050 三极管分立驱动电路(解决 IO 驱动弱问题)
若使用无驱动裸蜂鸣器,或想用 3.3V 单片机控制 5V 蜂鸣器,需搭配 S8050 三极管搭建开关电路,电路连线逻辑:
- 单片机 PA7 → 1K 限流电阻 R1 → S8050 三极管基极 B
- 三极管集电极 C 接系统 VCC
- 三极管发射极 E 分两路并联负载:
- 支路 1:1K 限流电阻 R2 + LED 正极,LED 负极接 GND
- 支路 2:有源蜂鸣器正极,蜂鸣器负极接 GND
三、电路工作原理详解
3.1 成品有源蜂鸣器模块驱动原理(直接接 PA7 方案)
有源蜂鸣器内部集成振荡电路,不需要单片机输出 PWM 方波,仅靠直流高低电平即可控制启停:
- PA7 输出 0V 低电平:模块输入无效,内部振荡电路停止,蜂鸣器静音;
- PA7 输出 3.3V 高电平:模块输入有效,内置振荡器驱动发声元件持续振动,输出固定音调声响。
单片机将 PA7 配置为 50MHz 推挽输出模式,推挽输出可以主动拉至高电平、拉低至 0V,驱动模块输入引脚;程序中通过两个函数控制电平:
- GPIO_SetBits (PA7):拉高引脚,蜂鸣器开启
- GPIO_ResetBits (PA7):拉低引脚,蜂鸣器关闭
3.2 S8050 三极管射极跟随驱动电路原理
- PA7 输出高电平:基极获得电流,三极管导通,发射极输出电压(3.3V-0.7V≈2.6V),LED 点亮、蜂鸣器发声;
- PA7 输出低电平:基极无压差,三极管完全截止,发射极无电压输出,LED 熄灭、蜂鸣器停止。
电路缺陷与优化方案
该射极跟随电路存在电压压降问题:3.3V 单片机 IO 驱动 5V 蜂鸣器时,负载仅得到 2.6V 电压,蜂鸣器音量微弱。 优化方案:改用共射极低侧开关电路,将蜂鸣器、LED 放在 VCC 与三极管集电极之间,发射极直接接地,消除电压损耗,3.3V IO 可完美驱动 5V 负载。
3.3 有源蜂鸣器 VS 无源蜂鸣器核心区别
很多新手踩坑分不清两者,这里整理对比表:
| 对比项 | 有源蜂鸣器(本实验使用) | 无源蜂鸣器 |
|---|---|---|
| 内部电路 | 自带振荡源 | 无振荡电路 |
| 控制方式 | 直流高低电平即可控制 | 必须定时器 PWM 方波驱动 |
| 恒定高电平效果 | 持续固定声音 | 仅 “咔” 一声,无法长鸣 |
| 音调修改 | 音调固定,无法软件调节 | 修改 PWM 频率即可变音 |
| 开发难度 | 简单,仅操作普通 GPIO | 复杂,需配置定时器 |
四、STM32 GPIO 配置底层逻辑
- 开启外设时钟:操作 GPIOA 前必须开启 APB2 时钟,时钟相当于端口工作许可,不开时钟 IO 口完全失效;
- 引脚模式配置:PA7 配置为通用推挽输出,速度 50MHz;推挽输出兼具灌电流、拉电流能力,适合驱动外部模块;
- 初始化防误响设计:初始化函数中先拉低 PA7 电平,再配置输出模式,避免上电瞬间电平抖动导致蜂鸣器乱响;
- 状态翻转函数:读取引脚当前输出电平,自动反向输出,适合按键触发、循环报警场景。
五、完整源代码分区(可直接复制)
5.1 工程文件架构
程序分层设计,蜂鸣器驱动单独封装,方便其他项目复用:
- HARDWARE/BEEP/BEEP.h:引脚宏定义、函数声明
- HARDWARE/BEEP/BEEP.c:蜂鸣器初始化、开关、翻转底层函数
- USER/main.c:主逻辑、OLED 状态打印、1 秒循环切换逻辑
5.2 BEEP.h 头文件
#ifndef __BEEP_H
#define __BEEP_H
#include "stm32f10x.h"
/* 有源蜂鸣器连接到 PA7,引脚输出高电平时蜂鸣器鸣叫。 */
#define BEEP_GPIO_PORT GPIOA
#define BEEP_GPIO_PIN GPIO_Pin_7
#define BEEP_GPIO_CLK RCC_APB2Periph_GPIOA
/* 初始化蜂鸣器 GPIO,初始化完成后蜂鸣器保持关闭。 */
void BEEP_Init(void);
/* PA7 输出高电平,开启蜂鸣器。 */
void BEEP_On(void);
/* PA7 输出低电平,关闭蜂鸣器。 */
void BEEP_Off(void);
/* 切换蜂鸣器当前状态。 */
void BEEP_Toggle(void);
#endif
5.3 BEEP.c 驱动文件
#include "BEEP.h"
void BEEP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 开启 GPIOA 外设时钟。 */
RCC_APB2PeriphClockCmd(BEEP_GPIO_CLK, ENABLE);
/* 配置输出模式前先将输出寄存器置低,避免初始化时蜂鸣器误响。 */
GPIO_ResetBits(BEEP_GPIO_PORT, BEEP_GPIO_PIN);
/* 将 PA7 配置为 50 MHz 通用推挽输出。 */
GPIO_InitStructure.GPIO_Pin = BEEP_GPIO_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(BEEP_GPIO_PORT, &GPIO_InitStructure);
/* 初始化结束后确保蜂鸣器处于关闭状态。 */
BEEP_Off();
}
void BEEP_On(void)
{
/* 有源蜂鸣器为高电平有效,PA7 置高后开始鸣叫。 */
GPIO_SetBits(BEEP_GPIO_PORT, BEEP_GPIO_PIN);
}
void BEEP_Off(void)
{
/* PA7 输出低电平,蜂鸣器停止鸣叫。 */
GPIO_ResetBits(BEEP_GPIO_PORT, BEEP_GPIO_PIN);
}
void BEEP_Toggle(void)
{
/* 读取 PA7 的输出状态,并切换为相反电平。 */
if(GPIO_ReadOutputDataBit(BEEP_GPIO_PORT, BEEP_GPIO_PIN) == Bit_RESET)
{
BEEP_On();
}
else
{
BEEP_Off();
}
}
5.4 main.c 主程序逻辑
/* Active buzzer and OLED teaching demonstration for STM32F103C8T6. */
#include "delay.h"
#include "oled.h"
#include "BEEP.h"
#define BEEP_STATE_TIME_MS 1000U
static void BEEP_ShowState(u8 is_on);
int main(void)
{
delay_init();
BEEP_Init();
OLED_Init();
OLED_ColorTurn(0);
OLED_DisplayTurn(0);
while(1)
{
BEEP_On();
BEEP_ShowState(1U);
delay_ms(BEEP_STATE_TIME_MS);
BEEP_Off();
BEEP_ShowState(0U);
delay_ms(BEEP_STATE_TIME_MS);
}
}
static void BEEP_ShowState(u8 is_on)
{
OLED_Clear();
OLED_ShowString(0, 0, (u8 *)"ACTIVE BEEP", 16);
OLED_ShowString(0, 18, (u8 *)"PIN: PA7", 16);
if(is_on != 0U)
{
OLED_ShowString(0, 36, (u8 *)"LEVEL: HIGH", 16);
OLED_ShowString(0, 52, (u8 *)"BUZZER: ON", 12);
}
else
{
OLED_ShowString(0, 36, (u8 *)"LEVEL: LOW", 16);
OLED_ShowString(0, 52, (u8 *)"BUZZER: OFF", 12);
}
OLED_Refresh();
}
代码修改拓展说明
修改宏定义 BEEP_STATE_TIME_MS 即可调整鸣叫节奏:
- 改为 500:0.5 秒切换一次,急促滴滴声
- 改为 2000:2 秒切换一次,慢速间歇报警 有源蜂鸣器无法通过代码修改音调,想要播放音乐需要更换无源蜂鸣器,增加定时器 PWM 驱动代码。
六、实物演示与调试章节
6.1 实物接线步骤
- 按照上文接线表,先连接所有 GND 共地线路,再依次接 OLED、蜂鸣器信号线;
- 给开发板上电,观察上电瞬间蜂鸣器无短促异响(初始化拉低电平生效);
- 屏幕点亮,第一帧显示
LEVEL:LOW、BUZZER:OFF,等待 1 秒自动切换状态; - 蜂鸣器交替鸣叫、静音,屏幕文字同步变化,无延迟。
6.2 万用表实测验证方法
调试时可用万用表直流电压档测量 PA7 引脚电压,验证软硬件一致性:
- OLED 显示 HIGH 时,PA7 电压≈3.3V;
- OLED 显示 LOW 时,PA7 电压≈0V; 若电压和屏幕显示不匹配,排查 GPIO 初始化、接线虚焊问题。

6.3 常见故障排查表
| 故障现象 | 排查原因 | 解决办法 |
|---|---|---|
| 蜂鸣器完全不响 | 接线漏接 GND、VCC 供电错误、PA7 虚焊 | 重新核对所有地线,确认蜂鸣器供电电压 |
| 上电一直长鸣 | 模块为低电平有效、引脚接错 | 修改 BEEP_On/BEEP_Off 电平逻辑,更换控制引脚测试 |
| OLED 正常,蜂鸣器声音微弱 | 3.3V IO 直驱 5V 蜂鸣器,电压压降 | 加装三极管共射驱动电路,或更换 3.3V 蜂鸣器模块 |
| 屏幕状态和蜂鸣器声音相反 | 模块有效电平与代码逻辑冲突 | 互换 BEEP_On、BEEP_Off 内部高低电平操作 |
| 修改延时参数,音调无变化 | 当前使用有源蜂鸣器 | 更换无源蜂鸣器,新增定时器 PWM 驱动代码 |
七、总结
- 本实验使用有源蜂鸣器,仅需普通 GPIO 高低电平控制,无需 PWM,开发门槛低;
- 硬件接线核心要点:全部外设与 STM32 共地,蜂鸣器供电严格匹配模块额定电压;
- 三极管射极跟随电路可拓展驱动大功率负载,但存在电压损耗,3.3V 控 5V 负载推荐改用共射开关电路;
- 分层封装蜂鸣器驱动代码,配合 OLED 实时状态打印,方便直观调试 GPIO 输出逻辑;
- 想要实现多音调、音乐播放,必须替换无源蜂鸣器,搭配定时器输出不同频率方波驱动。
更多推荐


所有评论(0)