一、音乐编码生成器使用
对于用户来说,想要让蜂鸣器发出需要的音乐,就得需要提供乐谱,本文以《生日快乐》为例,介绍如何把乐曲变为编码,再由编码变为音乐的流程。
将乐谱转换为编码的软件为《Music Encode》,使用该软件对照乐谱即可生成编码;《生日快乐》乐谱如图1所示,打开《Music Encode》软件,按照图中乐谱的对应的音符输入到如图2所示的软件中,输入完成后点击“开始转换”就会生成十六进制的数组,单片机蜂鸣器播放程序使用该数组就可以播放对应的音乐。
图1 《生日快乐》乐谱
图1 music encode 界面
二、蜂鸣器播放程序
音乐播放程序
#include "SoundPlay.h"
/**************************************************************************
SOUND PLAY FOR nRF52832MCU
COPYRIGHT (c) 2005 BY JJJ.
-- ALL RIGHTS RESERVED --
File Name: SoundPlay.h
Author: Jiang Jian Jun / jason xiao
Created: 2005/5/16
Modified: 2020/3/9
Revision: 1.1
*******************************************************************************/
//**************************************************************************
#define SOUND_SPACE 3/4
unsigned int FreTab[12] = { 262,277,294,311,330,349,369,392,415,440,466,494 };
unsigned char SignTab[7] = { 0,2,4,5,7,9,11 };
unsigned char LengthTab[7]= { 1,2,4,8,16,32,64 };
unsigned char Sound_Temp_TH0,Sound_Temp_TL0;
unsigned char Sound_Temp_TH1,Sound_Temp_TL1;
//**************************************************************************
//**************************************************************************
void Play(unsigned char *Sound,unsigned char Signature,unsigned char Octachord,unsigned int Speed)
{
unsigned int NewFreTab[12];
unsigned char i,j;
unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
for(i=0;i<12;i++)
{
j = i + Signature;
if(j > 11)
{
j = j-12;
NewFreTab[i] = FreTab[j]*2;
}
else
NewFreTab[i] = FreTab[j];
if(Octachord == 1)
NewFreTab[i]>>=2;
else if(Octachord == 3)
NewFreTab[i]<<=2;
}
SoundLength = 0;
while(Sound[SoundLength] != 0x00)
{
SoundLength+=2;
}
Point = 0;
Tone = Sound[Point];
Length = Sound[Point+1];
LDiv0 = 12000/Speed;
LDiv4 = LDiv0/4;
LDiv4 = LDiv4-LDiv4*SOUND_SPACE;
while(Point < SoundLength)
{
SL=Tone%10;
SM=Tone/10%10;
SH=Tone/100;
CurrentFre = NewFreTab[SignTab[SL-1]+SH];
if(SL!=0)
{
if (SM==1) CurrentFre >>= 2;
if (SM==3) CurrentFre <<= 2;
Temp_T = (500000/CurrentFre) + 12;//定时器溢出值设定为 500000/CurrentFre+12 us
}
SLen=LengthTab[Length%10];
XG=Length/10%10;
FD=Length/100;
LDiv=LDiv0/SLen;
if (FD==1)
LDiv=LDiv+LDiv/2;
if(XG!=1)
if(XG==0)
if (SLen<=4)
LDiv1=LDiv-LDiv4;
else
LDiv1=LDiv*SOUND_SPACE;
else
LDiv1=LDiv/2;
else
LDiv1=LDiv;
if(SL==0) LDiv1=0;
LDiv2=LDiv-LDiv1;
if (SL!=0 && LDiv1!=0)
{
u32 sustainTimeUs,sustainCnt =0;
sustainTimeUs = (10*LDiv1*1000)/Temp_T;
while(sustainCnt++< sustainTimeUs)
{
nrf_gpio_pin_toggle(BUZZER_PIN);
nrf_delay_us(Temp_T);
}
}
if(LDiv2!=0)
{
nrf_gpio_pin_set(BUZZER_PIN);
for(i=LDiv2;i>0;i--)
{
nrf_delay_ms(10);//延迟10ms
}
}
Point+=2;
Tone=Sound[Point];
Length=Sound[Point+1];
}
}
//**************************************************************************
unsigned char Music_Three[] = {0x0F,0x03, 0x0F,0x03, 0x10,0x02, 0x0F,0x02, 0x15,0x02,
0x11,0x01, 0x00,0x00 };
u8 SignatureC = 8;
u8 octachordC = 2;
u16 speedC = 80;
void example(void)
{
Play(Music_Three,SignatureC,octachordC,speedC);
}