单片机:实现生日快乐歌(附带源码)

单片机实现《生日快乐歌》

实现一个“生日快乐歌”是单片机应用中的一个经典项目,通过它可以学习如何控制声音输出、使用定时器、以及如何处理按键输入等功能。本项目将利用单片机生成《生日快乐歌》的音频信号,并通过蜂鸣器播放出来。

项目目标

本项目的目标是设计并实现一个基于8051单片机的“生日快乐歌”播放系统。系统会通过蜂鸣器输出《生日快乐歌》的旋律,当按下一个按键时,系统播放这首歌。

一、硬件设计
1.1 单片机选择

本项目采用8051单片机,它具备丰富的I/O端口,可以与蜂鸣器连接,并且支持定时器,可以用来产生音频信号。

1.2 外部硬件
  • 蜂鸣器:作为输出设备,通过蜂鸣器发出不同频率的音符,模拟乐曲的旋律。
  • 按键:用于触发《生日快乐歌》的播放。假设使用一个简单的按键,按下时开始播放歌曲。
  • 定时器:用定时器来产生一定频率的脉冲信号,以控制蜂鸣器发出不同的音高。
  • 电源和电阻:用于电路的供电和保护。
1.3 硬件连接
  1. 蜂鸣器连接:蜂鸣器连接到P1.0端口,利用PWM信号驱动蜂鸣器发出声音。
  2. 按键连接:按键连接到P3.0端口,用来触发播放《生日快乐歌》。
二、系统设计
2.1 功能模块
  1. 音符生成模块:通过定时器产生不同频率的脉冲信号,驱动蜂鸣器发出不同频率的声音,形成音符。
  2. 按键触发模块:通过按键输入,触发歌曲的播放。
  3. 歌曲存储和播放模块:存储《生日快乐歌》中的音符频率和时长,依次播放。
2.2 数据结构
  • 音符频率:将歌曲中的每个音符频率(如C4、D4等)存储为一个数组,方便播放。
  • 音符时长:每个音符的时长也可以通过数组存储,控制每个音符的持续时间。
  • 当前音符:当前播放的音符。
2.3 歌曲结构

《生日快乐歌》的音符和时长如下(以C4为基础音符):

音符频率(Hz)时长(ms)
C4261.63400
C4261.63400
D4293.66400
C4261.63800
F4349.23400
F4349.23400
E4329.63400
C4261.63800
C4261.63400
C4261.63400
D4293.66400
C4261.63800
三、程序设计
3.1 定时器中断

利用定时器中断来生成频率对应的音符。通过设置定时器初值,可以生成一定频率的脉冲信号,从而控制蜂鸣器发出相应的音符。

3.2 主程序框架
  1. 初始化定时器和蜂鸣器
  2. 按键扫描:监听按键的输入,当按下按键时触发歌曲播放。
  3. 音符生成和播放:根据音符的频率和时长,通过定时器产生相应的脉冲信号,控制蜂鸣器的鸣响。
  4. 音符播放结束后继续播放下一音符,直到歌曲播放完毕。
3.3 代码实现
#include <reg51.h>   // 包含8051的寄存器定义

// 定义蜂鸣器连接端口
#define BEEP P1_0

// 定义按键连接端口
#define BUTTON P3_0

// 定义音符的频率(单位:Hz)
#define C4 261
#define D4 293
#define E4 329
#define F4 349

// 定义音符时长(单位:毫秒)
#define NOTE_DURATION 400  // 默认音符时长

// 定义音符数组,按照《生日快乐歌》的音符顺序
unsigned int melody[] = {C4, C4, D4, C4, F4, F4, E4, C4, C4, C4, D4, C4};
unsigned int melody_duration[] = {NOTE_DURATION, NOTE_DURATION, NOTE_DURATION, NOTE_DURATION, NOTE_DURATION, NOTE_DURATION, NOTE_DURATION, NOTE_DURATION, NOTE_DURATION, NOTE_DURATION, NOTE_DURATION, NOTE_DURATION};

// 定时器初始化,产生固定频率的脉冲
void timer0_init() {
    TMOD = 0x01;  // 设置定时器0为模式1(16位定时器)
    IE = 0x82;    // 使能定时器中断
    TR0 = 1;      // 启动定时器0
}

// 延时函数(单位:毫秒)
void delay_ms(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++) {
        for (j = 0; j < 120; j++) {
            // 空循环,产生延时
        }
    }
}

// 播放音符
void play_tone(unsigned int frequency, unsigned int duration) {
    unsigned int i;
    unsigned int delay_time = 1000000 / frequency;  // 计算每个周期的延时
    unsigned int cycles = frequency * duration / 1000;  // 计算音符持续的周期数
    
    for (i = 0; i < cycles; i++) {
        BEEP = 1;  // 启动蜂鸣器
        delay_ms(delay_time / 2);  // 延时一半周期
        BEEP = 0;  // 关闭蜂鸣器
        delay_ms(delay_time / 2);  // 延时另一半周期
    }
}

// 按键扫描函数
unsigned char key_scan() {
    if (BUTTON == 0) {
        delay_ms(20);  // 去抖动
        return 1;  // 按键被按下
    }
    return 0;
}

// 主程序
void main() {
    unsigned int i;
    timer0_init();  // 初始化定时器
    
    while (1) {
        if (key_scan()) {  // 如果按键被按下
            for (i = 0; i < sizeof(melody) / sizeof(melody[0]); i++) {
                play_tone(melody[i], melody_duration[i]);  // 播放音符
                delay_ms(100);  // 音符之间的间隔
            }
        }
    }
}
四、程序说明
  1. 定时器初始化timer0_init()函数初始化定时器0为模式1(16位定时器),启用定时器中断来产生音频信号。
  2. 按键扫描key_scan()函数用来检测按键是否被按下,若按键按下,则启动播放《生日快乐歌》。
  3. 音符播放play_tone()函数根据音符的频率和时长,生成脉冲信号,控制蜂鸣器发出相应的音符。
  4. 音符和时长数组melody[]数组存储《生日快乐歌》的音符,melody_duration[]数组存储每个音符的时长。
五、优化与扩展
  1. 多音符支持:可以扩展音符数组,增加更多的音符和歌曲。
  2. 使用LCD显示:通过LCD显示屏显示歌曲的进度或歌曲名。
  3. 音量调节:通过PWM信号控制蜂鸣器的音量,提供音量调节功能。
  4. 多段歌曲支持:将不同的歌曲分段存储,增加多种歌曲选择功能。
六、总结

通过本项目,我们学习了如何通过单片机控制蜂鸣器发出不同频率的声音,模拟乐曲的旋律。同时,这个项目也展示了如何用8051单片机处理定时器、按键输入和音符生成等基本功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值