1、蜂鸣器播放器程序的设计
音乐的产生主要是通过单片机的I/O口输出高低不同的脉冲信号来控制蜂鸣器发音,要想产生音频脉冲信号,需要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。利用单片机定时器计时这个半个周期时间,每当计时到后就将输出脉冲的I/O口反相,然后重复计时此半周期时间再对I/O口反相,这样就能在此I/O口上得到此频率的脉冲。
每个音符使用一个字节,字节的高四位代表音符的高低,低四位代表音符的节拍,表5-2为节拍与节拍码的对照表。如果1拍为0.4s,1/4拍是0.1s只要设定延迟时间就可求得节拍的时间。假设1/4拍为1个延迟单位时间,那么1拍对应的就是4个延迟单位时间,以此类推。所以只要求得1/4拍的延迟单位时间,其余的节拍就是它的倍数,表5-3为1/4拍和1/8拍的时间设定。
音符数据结构表示:
typedef struct Tonedata{
short note;//音符:0 表示不发音。1 2 3 4 5 6 7
shorttone;//音调:1 低音,2 中
short length;//长度//1表示四分之一拍,8表2拍
}Tone,*PTone;
在一个程序中,需要演奏两首或两首以上歌曲时,音乐代码库的建立有两种方法:
(1) 将每首歌曲建立相互独立的音符表T和发音符计数值表(TABLE)。
(2) 也可以建立共用的音符表T后,再写每首歌曲的发音计数值表(TABLE)中的代码。
不管采用哪种方法,每首歌曲结束时,在发音计数值表(TABLE)中均需加上音乐结束符00H。
歌曲数据结构定义:
typedef struct SongData
{ unsigned int length;//歌曲长度
PTone pData; } Song,*PSong;
2.3 程序实现
下面以歌曲《送别》的设计为例,讲述歌曲在单片机中实现自动演奏。歌曲《送别》如下所示:
歌曲对应编码如下:
Tone songdata2[65]= { {5,2,4},{3,2,2},{1,3,8},{6,2,4},{1,3,4},{5,2,8},{0,0,2},{5,2,4},{1,2,2},{2,2,2},{3,2,4},{2,2,2},{1,2,2},{2,2,8},{0,0,8},{5,2,4},{3,2,2},{5,2,2},{2,2,4},{1,3,6},{7,2,2},{6,2,4},{1,3,4},{5,2,8},{5,2,4},{2,2,2},{3,2,2},{4,2,6},{7,1,2},{1,2,8},{0,0,8},{6,2,4},{1,3,4},{0,0,1},{1,3,8},{7,2,4},{6,2,2},{7,2,2},{1,3,8},{6,2,2},{7,2,2},{1,3,2},{6,2,2},{6,2,2},{5,2,2},{2,2,2},{1,2,2},{2,2,8},{0,0,8},{5,2,4},{3,2,2},{5,2,2},{1,3,8},{7,2,2},{6,2,4},{1,3,4},{5,2,8},{0,0,1},{5,2,4},{2,2,2},{3,2,2},{4,2,8},{7,1,2},{1,2,12},{0,0,4}};//送别-李叔同
程序主函数如下:
int32_t main(void)
{ uint32_t temp,MidDid;
&nbs