1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 51单片机实现用无源蜂鸣器或扬声器播放简单音乐

51单片机实现用无源蜂鸣器或扬声器播放简单音乐

时间:2018-06-08 06:42:06

相关推荐

51单片机实现用无源蜂鸣器或扬声器播放简单音乐

实现原理

通过PNP三极管提高单片机管脚带负载能力,其中R5电阻为上拉电阻以确保在单片机未置低时保证三极管完全关断。通过控制喇叭响与不响的时间长度得到不同音高,故而需要使用定时器定时开关喇叭。

具体实现

//下列中CD为超低音部,D为低音部,Z为中音部,G为高音部,CG为超高音部//每组注释第一行为数组序号,第二行为在C调中的简谱符号//该结构体用于存放定时器初值以改变扬声器震动频率unsigned int code pinlv[]={0,6,62211,62398,62574,62740,62897,63045,63185,63317,//123456789//CD1 CD1.5 CD2 CD2.5 CD3 CD4 CD4.5 CD5 CD5.5 63441,63559,63670,//10 11 12//CD6 CD6.5 CD763775,63874,63967,64055,64138,64217,64291,64361,64426,//13 14 15 16 17 18 19 20 21//D1 D1.5 D2 D2.5 D3 D4 D4.5 D5 D5.5 64489,64548,64603,//22 23 24//D6 D6.5 D764655,64705,64751,64795,64837,64876,64913,64948,64981,//25 26 27 28 29 30 31 32 33//Z1 Z1.5 Z2 Z2.5 Z3 Z4 Z4.5 Z5 Z5.5 65012,65042,65069,//34 35 36//Z6 Z6.5 Z765096,65121,65144,65166,65187,65206,65225,65242,65259,//3738 3940 4142 4344 45//G1 G1.5 G2 G2.5 G3 G4 G4.5 G5 G5.5 65274,65289,65303,//46 47 48//G6 G6.5 G765316,65328,65340,65351,65361,65371,65380,65389,65397,//4950 5152 5354 5556 57//CG1 CG1.5 CG2 CG2.5 CG3 CG4 CG4.5 CG5 CG5.5 65405,65412,65420//CG//5859 60//CG6 CG6.5 CG7};

根据上方的结构体就能编写出大部分你想编写的音符,但是音色取决于你的无源蜂鸣器或者喇叭(能震就行)。算这个费老大劲,有觉得音准不行的自己改改,在下尽力了。

PS:我用的无源蜂鸣器播放的音色不能说娓娓动听吧,但也算是阴曹地府风了。

void Timer0Init(void){TMOD = 0x01;TL0 = 0x66;TH0 = 0xFC;TF0 = 0;TR0 = 1;ET0=1; EA=1;}void Timer0_Routine() interrupt 1{TL0 = pinlv[expected_pinlv]%256;TH0 = pinlv[expected_pinlv]/256;speaker=!speaker;}

上方是定时器初始化还有中断服务函数,结合一下就这么用。

上面的expected_pinlv变量名称土洋结合了属于是,应该都能看懂,给他赋值就是一开始那个存放频率的结构体的序号,为了方便直接从1开始数,注释都写好了,应该没大问题。

u16 beat_transform(u16 beat){u16 need_ms;switch(beat){case 1: need_ms=ms_every_beat/8;break;case 2: need_ms=ms_every_beat/4;break;case 3: need_ms=ms_every_beat/2;break;case 4: need_ms=ms_every_beat;break;case 5: need_ms=ms_every_beat*2;break;case 6: need_ms=ms_every_beat*3;break;case 7: need_ms=ms_every_beat*4;break;case 8: need_ms=ms_every_beat*5;break;case 9: need_ms=ms_every_beat*6;break;default: break;}return need_ms;}void speed_transform(u16 speed){ms_every_beat=60000/speed;//ms_every_beat设置为全局变量较方便}

要是有点小追求,咱稍微严格点吧节拍速度算个大概,然后用个准确点的1ms软件延时函数,节奏就能比较完满的复刻出来。可惜我搞的软件延时差的还有点大,懒得整了,贴出来你们想玩试试。

下面给个例子哈,是个模板,不一定能用,最后我会分享一个.c文件是我试过能用的,要是不能用那大概率因为硬件不一样,勿diss我。

//太阳照常升起 115速//每行是一小节//格式:频率序号,拍数//拍数规则:1代表1/8拍 2代表1/4拍 3代表1/2拍 4代表1拍 5代表2拍以此类推unsigned int code music_taiyang[]={27,4, 34,4, 34,4, 34,3, 34,2, 35,2,34,5, 34,4, 35,3, 36,3,39,4, 39,4, 37,4, 37,4,34,7, 27,4, 32,4, 32,4, 32,3, 34,3,32,5, 34,5,37,3, 34,3, 37,5, 29,3, 30,3,27,8,27,4, 30,4, 34,4,39,3, 37,3, 39,5, 39,3, 37,3,39,3, 37,3, 39,5, 37,3, 37,3,34,8,32,4, 39,4, 37,4,34,3, 32,3,34,7, 32,4, 39,4, 36,4, 34,3, 32,3, 34,4, 37,4, 39,3, 30,3,27,7,100};int main(void){Timer0Init();speed_transform(115); while(1){if(music_taiyang[i]==100) i=0; expected_pinlv=music_taiyang[i]; i++; delay_ms(beat_transform(music_taiyang[i])-10); i++; speaker=1;delay_ms(10); //这里减10ms是为了让音之间转换能清晰点,不用也行}}

前面定义过的函数没在上面再写,用大概就这么用。里面的延时函数需要自己写一下,我写的不准就不贴出来浪费大家时间了。

链接:/s/1F6GjlayIs10k95aMf5DUbA

提取码:2333

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。