单片机——蜂鸣器(生日快乐歌)

基础知识

  • 改变单片机引脚输出波形的频率,就可以调整控制蜂鸣器音调,产生各种不同音色、音调的声音。

  • 改变输出电平的高低电平占空比,(占空比是指一个周期内高电平所占的时间)则可以控制蜂鸣器的声音大小。

  • 单片机采用的是无源蜂鸣器,需要产生一定的脉冲才能够让蜂鸣器发声,这是蜂鸣器发声的主要原理。(原理图如下)

  • p15端口是蜂鸣器电压的输入端口,根据不同单片机原理图不一样,此端口也不一样,一定要看清楚。
    在这里插入图片描述

程序代码

1.简单驱动

#include"reg52.h"

typedef unsigned char u8;
typedef unsigned int u16;

sbit  beep=P1^5;

void delay(u16 i)
{
    while(i--);
}
	
void main()
{   
	 while(1) 
	 {
	     beep=~beep;   //p1.5端口电压取反,因此产生了脉冲
		 delay(10);     //改变延迟时间可以改变频率
	 }
}

2.生日快乐歌

#include <reg51.h>

#define uint unsigned int 
#define uchar unsigned char

sbit beep = P1^5;

uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159,
212,212,106,126,159,169,190,119,119,126,159,142,159,0};
uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,
9,3,12,12,12,12,12,9,3,12,12,12,24,0};

//延时函数
void DelayMS(uint x)
{
     uchar t;
     while(x--) for(t=0;t<120;t++);
}

//控制音频、节拍函数
void PlayMusic()
{
     uint i=0,j,k;
     while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
 {   
     for(j=0;j<SONG_LONG[i]*20;j++)  //播放各个音符,SONG_LONG 为拍子长度
   {
         beep=~beep;
         for(k=0;k<SONG_TONE[i]/3;k++);//SONG_TONE 延时表决定了每个音符的频率
   }
    DelayMS(10);
    i++;
 }
}

void main()
{
    beep=0;
    while(1)
    {
        PlayMusic(); //播放生日快乐
        DelayMS(500); //播放完后暂停一段时间
    }
}
  • 55
    点赞
  • 300
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
A: 要使用STM32单片机蜂鸣器播放生日快乐,可以按照以下步骤进行: 1. 根据芯片型号和引脚定义连接蜂鸣器,如使用PA8引脚连接蜂鸣器。 2. 通过初始化时钟功能,设置系统时钟。 3. 通过GPIO功能,设置PA8引脚为输出模式。 4. 设置蜂鸣器的频率和音量大小,可以通过修改发声时间和空声时间,调节音量大小。 5. 使用循环结构,播放生日快乐曲。 以下是基于HAL库编写的生日快乐播放程序示例: ``` #include "stm32f1xx_hal.h" /* 定义蜂鸣器引脚 */ #define BUZZER_PIN GPIO_PIN_8 #define BUZZER_PORT GPIOA /* 定义发声时间、空声时间和音量大小 */ #define NOTE_A 440 #define NOTE_AS 466 #define NOTE_B 494 #define NOTE_C 523 #define NOTE_CS 554 #define NOTE_D 587 #define NOTE_DS 622 #define NOTE_E 659 #define NOTE_F 698 #define NOTE_FS 740 #define NOTE_G 784 #define NOTE_GS 831 #define NOTE_A2 880 /* 定义蜂鸣器音量大小 */ #define BUZZER_VOLUME 100 /* 定义曲节拍表 */ uint16_t happy_birthday[54][2] = { {NOTE_C, 500}, {NOTE_C, 500}, {NOTE_D, 500}, {NOTE_C, 600}, {NOTE_F, 500}, {NOTE_E, 500}, {NOTE_C, 1000}, {NOTE_C, 500}, {NOTE_C, 500}, {NOTE_D, 500}, {NOTE_C, 600}, {NOTE_G, 500}, {NOTE_F, 500}, {NOTE_C, 1000}, {NOTE_C, 500}, {NOTE_C, 500}, {NOTE_C2, 500}, {NOTE_A, 600}, {NOTE_F, 500}, {NOTE_E, 500}, {NOTE_D, 500}, {NOTE_AS, 500}, {NOTE_A, 500}, {NOTE_G, 500}, {NOTE_F, 1000}, {NOTE_C, 500}, {NOTE_C, 500}, {NOTE_C2, 500}, {NOTE_A, 600}, {NOTE_F, 500}, {NOTE_E, 500}, {NOTE_D, 500}, {NOTE_DS, 500}, {NOTE_D, 500}, {NOTE_C, 750}, {NOTE_C, 250}, {NOTE_C, 500}, {NOTE_C, 500}, {NOTE_C2, 500}, {NOTE_A, 600}, {NOTE_F, 500}, {NOTE_E, 500}, {NOTE_D, 500}, {NOTE_DS, 500}, {NOTE_D, 500}, {NOTE_C2, 750}, {NOTE_C2, 250}, {NOTE_C, 500}, {NOTE_C, 500}, {NOTE_C2, 500}, {NOTE_AS, 600}, {NOTE_F, 500}, {NOTE_G, 500}, {0, 1000}, }; /* 等待给定时间 */ void delay_ms(uint32_t ms) { HAL_Delay(ms); } /* 播放蜂鸣器 */ void beep(uint16_t frequency, uint32_t duration) { uint32_t period_us = 1000000 / frequency; // 每个周期的时间(单位:微秒) uint16_t cycles = duration * BUZZER_VOLUME / period_us / 2; // 蜂鸣器需要的周期数 for (uint16_t i = 0; i < cycles; i++) { HAL_GPIO_WritePin(BUZZER_PORT, BUZZER_PIN, GPIO_PIN_SET); // 置高电平 delay_ms(period_us * 0.5 * 0.001 / BUZZER_VOLUME); // 延时半个周期 HAL_GPIO_WritePin(BUZZER_PORT, BUZZER_PIN, GPIO_PIN_RESET); // 置低电平 delay_ms(period_us * 0.5 * 0.001 / BUZZER_VOLUME); // 延时半个周期 } } /* 播放曲 */ void play_song(uint16_t song[][2], uint16_t length) { for (uint16_t i = 0; i < length; i++) { uint16_t note_frequency = song[i][0]; uint32_t note_duration = song[i][1]; if (note_frequency == 0) { delay_ms(note_duration); // 空音符 } else { beep(note_frequency, note_duration); // 播放音符 } delay_ms(50); // 加上间隔,保证每个音符之间的时间间隔 } } int main(void) { HAL_Init(); __HAL_RCC_GPIOA_CLK_ENABLE(); // 启用GPIOA时钟 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = BUZZER_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(BUZZER_PORT, &GPIO_InitStruct); // 配置蜂鸣器引脚为输出模式 while (1) { play_song(happy_birthday, 54); // 播放生日曲 } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值