1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 单片机通过蜂鸣器播放任意音乐代码实现(1):单片机代码部分

单片机通过蜂鸣器播放任意音乐代码实现(1):单片机代码部分

时间:2024-03-20 13:09:59

相关推荐

单片机通过蜂鸣器播放任意音乐代码实现(1):单片机代码部分

单片机通过蜂鸣器播放任意音乐代码实现(1):单片机代码部分

有时候我们需要借助单片机实现音乐播放,可行的方案有很多,但成本最低的方案还是通过单片机驱动蜂鸣器来实现音乐播放。本文通过改进常见的单片机驱动蜂鸣器方法,一定程度上实现了任意音乐可以通过蜂鸣器播放(能听出来的程度)。不再需要手动输入乐谱参数,大大节省了时间和提高了准确度。

所用软件

keil 5(C51) V5.27.1.0:用于编写、编译C程序并生成hex文件Proteus 8 Professional V8.9:用于单片机仿真

1.根据国际标准音高求出定时器计数值

国际标准音高包含了哆啦咪法嗦来嘻(表中用1234567)的多个音高的频率,为了尽可能的还原音乐,这里模拟了其中9个频率的音高。下表为音高对应的频率。

接下来根据T=65535-1/频率1/2/1.0851000000+1的公式,在EXCEL表格中添加此公式,可以很快求出各个音高对应的计数值。下图便是上述频率对应的计数值:

到这里还不算完,因为51单片机定时器计数值分为高位计数值和低位计数值两个部分。所以还需要将上述10进制计数值转为16进制计数值,这样便能直接将2进制的计数值分割成高位和低位两部分。 实现方法很简单,在EXCEL中编辑=DEC2HEX(单元格)便能将对应单元格的10进制计数值转为16进制计数值。下图便是上述10进制计数值对应的16进制计数值:

2.定时器还原音高、延时函数还原音长

为了实现音乐的还原,设计采用定时器中断产生一定频率的方波信号驱动无源蜂鸣器还原音高,延时函数将使该频率维持特定时间还原音长。这样便能实现简谱上一个音符的还原,连贯起来便能还原整段音乐。

2.1 添加音高对应的定时器计数值常量至ROM(9个音高)

code unsigned char yingaoh[63]={0x92,0xC8,0xE4,0xF2,0xF9,0xFC,0xFE,0xFF,0xFF, //音符1的9个音高0x9E,0xCE,0xE7,0xF3,0xF9,0xFC,0xFE,0xFF,0xFF,//音符2的9个音高0xA8,0xD4,0xEA,0xF5,0xFA,0xFD,0xFE,0xFF,0xFF, //音符3的9个音高0xAD,0xD6,0xEB,0xF5,0xFA,0xFD,0xFE,0xFF,0xFF, //音符4的9个音高0XB6,0XDB,0XED,0XF6,0XFB,0XFD,0XFE,0XFF,0XFF, //音符5的9个音高0XBE,0XDF,0XEF,0XF7,0XFB,0XFD,0XFE,0XFF,0XFF, //音符6的9个音高0XC5,0XE2,0XF1,0XF8,0XFC,0XFE,0XFF,0XFF,0XFF, //音符7的9个音高}; //7个音符的9个八度高位计数值code unsigned char yingaol[63]={0x3C,0xF3,0x79,0x3C,0x1E,0x8F,0x47,0x23,0x91, //音符1的9个音高0x2A,0xF3,0x79,0xBC,0xDE,0xEF,0x77,0x3B,0x9D,//音符2的9个音高0x9D,0x4E,0x27,0x13,0x89,0x45,0xA2,0x51,0xA8, //音符3的9个音高0x6D,0xCE,0x61,0xB0,0xD8,0x6C,0xB6,0x5B,0xAD, //音符4的9个音高0X86,0X43,0XA1,0XD0,0X68,0XB4,0XDA,0X6D,0XB6, //音符5的9个音高0X8A,0X45,0XA2,0XD1,0XE8,0XF4,0XFA,0X7D,0XBE, //音符6的9个音高0XBE,0XD3,0X6C,0XB5,0X5A,0X2D,0X16,0X8B,0XC5,//音符7的9个音高}; 7个音符的9个八度低位计数值

2.2 添加音乐对应的单片机代码(丁香花)

其中music[0]为从musicxml中获取到的divisions值(下一节会介绍如何使用)、music[1]为每分钟节拍数、数组结尾放入0表示结束。中间的值按顺序每两个表示一个音高和维持的时间(需要通过换算求出实际时间)。

code unsigned char music[]={8,89,3,4,4,7,4,4,6,4,4,7,4,4,6,4,4,6,4,4,7,4,4,7,4,16,5,4,4,6,4,4,7,4,4,3,4,4,5,4,4,3,4,4,5,4,4,3,4,4,3,4,24,3,4,4,5,4,4,5,4,4,3,4,4,5,4,4,6,4,4,6,4,24,1,5,4,1,5,4,1,5,4,5,4,4,5,4,4,6,4,4,7,4,16,7,4,4,3,4,4,7,4,4,6,4,4,7,4,4,6,4,4,6,4,4,7,4,4,7,4,16,7,4,4,3,4,4,7,4,4,6,4,4,7,4,4,6,4,4,5,4,4,3,4,4,3,4,24,3,4,4,5,4,4,5,4,4,3,4,4,5,4,4,6,4,4,6,4,16,6,4,4,7,4,4,1,5,4,1,5,4,1,5,4,5,4,4,6,4,4,7,4,4,7,4,24,6,4,4,5,4,4,6,4,4,5,4,4,6,4,4,7,4,4,6,4,24,5,4,4,7,4,4,7,4,4,6,4,4,6,4,4,5,4,4,5,4,4,3,4,4,3,4,12,3,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,3,4,4,5,4,24,4,4,24,4,4,24,4,4,24,4,4,24,4,4,24,3,4,4,4,4,4,7,4,8,3,5,4,7,4,4,7,4,8,2,5,4,3,5,4,3,5,8,3,5,8,3,5,4,5,5,4,3,5,4,2,5,4,3,5,4,2,5,4,7,4,4,6,4,4,7,4,16,3,4,8,7,4,4,6,4,4,6,4,8,7,4,4,3,5,4,3,5,4,5,4,4,5,4,8,7,4,4,3,5,4,3,5,4,7,4,4,3,5,4,4,5,4,4,5,4,7,4,8,3,5,4,7,4,4,7,4,8,2,5,4,3,5,4,3,5,8,3,5,8,3,5,4,5,5,4,3,5,4,2,5,4,3,5,4,2,5,4,7,4,4,6,4,4,7,4,16,3,4,8,7,4,4,6,4,4,6,4,8,7,4,4,7,4,4,7,4,4,3,4,4,3,4,8,4,4,8,4,4,8,4,4,8,6,4,4,5,4,4,4,4,4,3,4,4,3,4,4,3,4,16,5,4,12,6,4,4,6,4,4,7,4,4,7,4,8,6,4,8,5,4,8,4,4,2,5,4,4,6,4,8,3,4,24,3,5,16,7,4,8,2,5,16,6,4,8,6,4,16,7,4,8,7,4,16,7,4,8,1,5,16,1,5,4,2,5,4,2,5,12,3,5,4,2,5,4,6,4,4,7,4,8,6,4,4,7,4,4,7,4,8,6,4,4,7,4,4,5,4,16,7,4,12,6,4,4,7,4,4,3,5,4,2,5,12,6,4,4,6,4,4,5,4,4,4,4,2,6,4,4,5,4,4,4,4,4,3,4,24,3,4,4,7,4,4,6,4,4,7,4,4,6,4,4,6,4,4,7,4,4,7,4,16,5,4,4,6,4,4,7,4,4,3,4,4,5,4,4,3,4,4,5,4,4,3,4,4,3,4,24,3,4,4,5,4,4,5,4,4,3,4,4,5,4,4,6,4,4,6,4,24,1,5,4,1,5,4,1,5,4,5,4,4,5,4,4,6,4,4,7,4,16,7,4,4,3,4,4,7,4,4,6,4,4,7,4,4,6,4,4,6,4,4,7,4,4,7,4,16,7,4,4,3,4,4,7,4,4,6,4,4,7,4,4,6,4,4,5,4,4,3,4,4,3,4,24,3,4,4,5,4,4,5,4,4,3,4,4,5,4,4,6,4,4,6,4,16,6,4,4,7,4,4,1,5,4,1,5,4,1,5,4,5,4,4,6,4,4,7,4,4,7,4,24,6,4,4,5,4,4,6,4,4,5,4,4,6,4,4,7,4,4,6,4,24,5,4,4,7,4,4,7,4,4,6,4,4,6,4,4,5,4,4,5,4,4,3,4,4,3,4,12,3,4,4,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,3,4,4,5,4,24,4,4,24,4,4,24,4,4,24,4,4,24,4,4,24,3,4,4,4,4,4,7,4,8,3,5,4,7,4,4,7,4,8,2,5,4,3,5,4,3,5,8,3,5,8,3,5,4,5,5,4,3,5,4,2,5,4,3,5,4,2,5,4,7,4,4,6,4,4,7,4,16,3,4,8,7,4,4,6,4,4,6,4,8,7,4,4,3,5,4,3,5,4,5,4,4,5,4,8,7,4,4,3,5,4,3,5,4,7,4,4,3,5,4,4,5,4,4,5,4,7,4,8,3,5,4,7,4,4,7,4,8,2,5,4,3,5,4,3,5,8,3,5,8,3,5,4,5,5,4,3,5,4,2,5,4,3,5,4,2,5,4,7,4,4,6,4,4,7,4,16,3,4,8,7,4,4,6,4,4,6,4,8,7,4,4,7,4,4,7,4,4,3,4,4,3,4,8,4,4,8,4,4,8,4,4,8,6,4,4,5,4,4,4,4,4,3,4,4,3,4,4,3,4,16,7,4,8,3,5,4,7,4,4,7,4,8,2,5,4,3,5,4,3,5,8,3,5,8,3,5,4,5,5,4,3,5,4,2,5,4,3,5,4,2,5,4,7,4,4,6,4,4,7,4,16,3,4,8,7,4,4,6,4,4,6,4,8,7,4,4,3,5,4,3,5,4,5,4,4,5,4,8,4,5,8,7,4,4,3,5,4,3,5,4,7,4,4,3,5,6,3,5,1,4,5,4,7,4,8,3,5,4,7,4,4,7,4,8,2,5,4,3,5,4,3,5,8,3,5,8,3,5,4,5,5,4,3,5,4,2,5,4,3,5,4,2,5,4,7,4,4,6,4,4,7,4,16,3,4,8,7,4,4,6,4,4,6,4,8,7,4,4,7,4,4,7,4,4,3,4,4,3,4,8,4,4,8,4,4,8,4,4,8,6,4,4,5,4,4,4,4,4,3,4,4,3,4,4,3,4,16,3,4,4,7,4,4,6,4,4,7,4,4,6,4,4,6,4,4,7,4,4,7,4,16,5,4,4,6,4,4,7,4,4,6,4,4,6,4,4,5,4,4,5,4,4,3,4,4,3,4,24,3,4,4,5,4,4,5,4,4,3,4,4,5,4,4,6,4,4,6,4,24,4,4,24,4,4,24,4,4,24,6,4,4,5,4,4,4,4,4,3,4,4,3,4,4,3,4,16,0};

2.3 音高模拟函数音高模拟函数实际上就是利用定时器中断产生一定频率方波驱动蜂鸣器发出一定频率的声音。

void t0int() interrupt 1 //定时器0中断函数{TR0=0; //关闭定时器TR0beep=!beep; //蜂鸣状态取反TH0=timeh; //把timeh赋给定时0高位计数值TL0=timel; //把timel赋给定时0低位计数值TR0=1; //开定时器TR0}

2.4 音长模拟函数音长模拟函数实际上就是让音高模拟函数运行一定时间,还原单个音符的发声。

void Delay10ms()//11.0592MHz下的10ms延时函数{unsigned char i, j;i = 108;j = 145;do{while (--j);} while (--i);}void jiepaidelay(float t) //节拍延时函数{unsigned int time;time=sifenyinfu*(t/km); //根据节拍算出10ms的计数次数 for(;time>0;time--){Delay10ms();}TR0=0;}

2.4 主函数设计主函数负责协调各个子函数的运作,实现循环播放音乐的功能。

int main(void){float k;unsigned int i;unsigned char m;float n;TMOD=0x01; //置T0定时器工作在方式1EA=1; //开总中断ET0=1; //开定时器0中断,这两句等效于IE=0x82i=2;km=music[0];//获取divisions值paizishu=music[1]; //获取曲子每分钟拍子数k=100*((60/paizishu)/4)+0.5; //根据每分钟节拍数,求解四分之一音符保持时长,四舍五入单位为10ms sifenyinfu=k;//把四分之一音符保持时长值赋给unsigned int型sifenyinfuwhile(1){m=(music[i]-1)*9+music[i+1]; //获取音符对应计数值所在下标n=music[i+2]; //获取音符保持时长值timeh=yingaoh[m]; //获取音符对应定时器计数值高位timel=yingaol[m]; //获取音符对应定时器计数值低位TH0=timeh;//把timeh赋给定时0高位计数值TL0=timel;//把timel赋给定时0低位计数值TR0=1; //开定时器0jiepaidelay(n); //执行音符保持函数i=i+3; //读下一个音符if(music[i]==0) i=2; //如果到末尾则回到开头,循环播放}}

3.使用Proteus 8 Professional V8.9进行仿真

如果你手边正好没有51单片机,或者你不想动手操作。接下来可以使用Proteus 8 Professional V8.9进行仿真。组成部分很简单,只有单片机和扬声器,注意一定要选择图下所示的扬声器才能发声(为了尽可能还原真实场景,最好把仿真软件中的速度晶振频率调整为11.0592MHz):

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