【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律

🔥小龙报:个人主页

🎬作者简介:C++研发,嵌入式,机器人方向学习者

❄️个人专栏:《工科必装软件安装教程》《嵌入式的开端 ---- 51单片机》
永远相信美好的事情即将发生

文章目录


前言

蜂鸣器是嵌入式设备中最基础的音频输出器件,广泛应用于各类电子设备的提示音、报警音场景。本文从蜂鸣器的核心原理入手,区分有源与无源蜂鸣器的差异,结合 51 单片机实操,先通过简单代码实现基础发声测试,再深入讲解定时器中断驱动的音乐演奏逻辑,完整实现《Happy New Year》的播放,帮助初学者吃透蜂鸣器的驱动与音频控制核心。

一、应用场景

大部分的电子产品、家电(风扇、空调、电水壶)都会有蜂鸣器,用于提示设备的工作状态

二、原理

蜂鸣器是一种将电信号转换为声音信号的器件,常用来产生设备的按键音、报警音等提示信号。​
蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器​

有源蜂鸣器 :内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定。​
无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音。​

注意: 蜂鸣器有正负极,顶部印有+号的为正极,若蜂鸣器引脚没剪,则长的为正极。

三、接线图

四、代码实现

4.1 测试代码

csharp 复制代码
#include<reg52.h>

sbit speak=P2^1;

//带参延时函数
void delay_ms(unsigned int xms)   //@12MHz
{
    unsigned int i, j;
    for(i=xms;i>0;i--)
    {
        for(j=124;j>0;j--)
        {}
    }
}

void main()
{
   while(1){
   speak=1;
   delay_ms(1);
   speak=0;
   delay_ms(1); 
   }
}

4.2 音乐演奏(Happy New Year)

csharp 复制代码
#include <reg52.h>

#define uchar unsigned char
sbit speak = P2 ^ 1;
bit flag = 0; // 标志音乐输出脚电平的高低
uchar ptr = 0x00;
uchar high;
uchar low;

uchar code music[] = {
    0xfc, 0x44, 0x7f, 0xfc, 0x44, 0x7f, 0xfc, 0x44, 0xff, 0xfa, 0x68, 0xff,
    0xfd, 0x23, 0x7f, 0xfd, 0x23, 0x7f, 0xfd, 0x23, 0xff, 0xfc, 0x44, 0xff,
    0xfc, 0x44, 0x7f, 0xfd, 0x23, 0x7f, 0xfd, 0x82, 0xff, 0xfd, 0x82, 0xff,
    0xfd, 0x23, 0x7f, 0xfd, 0x23, 0x7f, 0xfc, 0xac, 0xff, 0xff, 0xff, 0xff,
    0xfc, 0xac, 0x7f, 0xfd, 0x23, 0x7f, 0xfd, 0x34, 0xff, 0xfd, 0x34, 0xff,
    0xfd, 0x23, 0x7f, 0xfc, 0xac, 0x7f, 0xfd, 0x23, 0xff, 0xfc, 0x44, 0xff,
    0xfc, 0x44, 0x7f, 0xfd, 0x23, 0x7f, 0xfc, 0xac, 0xff, 0xfa, 0x68, 0xff,
    0xfc, 0x0c, 0x7f, 0xfc, 0xac, 0x7f, 0xfc, 0x44, 0xff, 0xff, 0xff, 0xff,
    0x00}; // happy new year 歌曲

// 带参延时函数
void delay_ms(unsigned int xms) //@12MHz
{
    unsigned int i, j;
    for (i = xms; i > 0; i--)
    {
        for (j = 124; j > 0; j--)
        {
        }
    }
}

void Count1(void) interrupt 1
{
    TH0 = high;
    TL0 = low;
    if (flag == 0)
    {
        speak = 0;
        flag = 1;
    }
    else
    {
        speak = 1;
        flag = 0;
    }
}

void Init()
{
    TMOD = 0x01;
    EA = 1;
    ET0 = 1;
}

void main()
{
    uchar time;
    Init();
    TH0 = high;
    TL0 = low;
    while (1)
    {
        if (music[ptr] != 0xff && music[ptr] != 0x00)
        {
            TR0 = 0;
            speak = 1;
            delay_ms(10);
            high = music[ptr];
            low = music[ptr + 1];
            time = music[ptr + 2];
            TR0 = 1;
            delay_ms(time);
            ptr += 3;
        }
        else if (music[ptr] == 0xff)
        {
            time = music[ptr + 2];
            delay_ms(time);
            ptr += 3;
        }
        else
        {
            TR0 = 0;
            speak = 1;
            delay_ms(2000);
            ptr = 0;
        }
    }
}

总结与每日励志

✨本文从蜂鸣器原理、接线到代码实现,完整覆盖了 51 单片机驱动蜂鸣器的核心方法:从简单延时翻转电平发声,到定时器中断动态调整频率实现音乐播放,层层递进拆解音频控制逻辑。嵌入式学习没有捷径,每一行代码的调试、每一个音调的校准,都是技术积累的过程。✨保持耐心,深耕细节,小小的蜂鸣器也能奏响你嵌入式之路的精彩乐章!

相关推荐
松涛和鸣10 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
简单中的复杂11 小时前
【避坑指南】RK3576 Linux SDK 编译:解决 Buildroot 卡死在 host-gcc-final 的终极方案
linux·嵌入式硬件
茉莉玫瑰花茶11 小时前
C++ 17 详细特性解析(5)
开发语言·c++·算法
上海合宙LuatOS11 小时前
LuatOS核心库API——【audio 】
java·网络·单片机·嵌入式硬件·物联网·音视频·硬件工程
cpp_250111 小时前
P10570 [JRKSJ R8] 网球
数据结构·c++·算法·题解
Hhh __灏11 小时前
stm32的SRAM内存不足如何分析和优化?堆栈空间如何优化?
单片机
cpp_250111 小时前
P8377 [PFOI Round1] 暴龙的火锅
数据结构·c++·算法·题解·洛谷
程序员老舅12 小时前
C++高并发精髓:无锁队列深度解析
linux·c++·内存管理·c/c++·原子操作·无锁队列
LS_learner12 小时前
Snapd和Apt—Linux 上两种完全不同的软件包管理系统
嵌入式硬件
点灯小铭12 小时前
基于51单片机的双档交流电压表设计与实现
单片机·嵌入式硬件·毕业设计·51单片机·课程设计·期末大作业