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

相关推荐
RuoZoe1 天前
重塑WPF辉煌?基于DirectX 12的现代.NET UI框架Jalium
c语言
blasit1 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
肆忆_2 天前
# 用 5 个问题学懂 C++ 虚函数(入门级)
c++
不想写代码的星星3 天前
虚函数表:C++ 多态背后的那个男人
c++
端平入洛4 天前
delete又未完全delete
c++
祈安_5 天前
C语言内存函数
c语言·后端
端平入洛5 天前
auto有时不auto
c++
norlan_jame6 天前
C-PHY与D-PHY差异
c语言·开发语言
琢磨先生David6 天前
Day1:基础入门·两数之和(LeetCode 1)
数据结构·算法·leetcode
哇哈哈20216 天前
信号量和信号
linux·c++