完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我想用单片机控制蜂鸣器播放一些音乐,用了一个八月桂花遍地开的程序,想把里面的歌曲改掉,用谱曲的软件改了之后,播放的就乱了,没有调子了。求高手解释下怎么改进啊!!原程序如下
/************************************************************************ [文件名] C51音乐程序(八月桂花) [功能] 通过单片机演奏音乐 /**********************************************************************/ #include #include //本例采用89C52, 晶振为11.0592MHZ //关于如何编制音乐代码, 其实十分简单,各位可以看以下代码. //频率常数即音乐术语中的音调,而节拍常数即音乐术语中的多少拍; //所以拿出谱子, 试探编吧! ***it Beep = P3^7 ; unsigned char n=0; //n为节拍常数变量 unsigned char code music_tab[] ={ //这里用取谱软件取出生日快乐的歌的代码后,播放时就乱码了。 0x18, 0x30, 0x1C , 0x10, //格式为: 频率常数, 节拍常数, 频率常数, 节拍常数, //求解释,望大家能帮帮忙。 0x20, 0x40, 0x1C , 0x10, 0x18, 0x10, 0x20 , 0x10, 0x1C, 0x10, 0x18 , 0x40, 0x1C, 0x20, 0x20 , 0x20, 0x1C, 0x20, 0x18 , 0x20, 0x20, 0x80, 0xFF , 0x20, 0x30, 0x1C, 0x10 , 0x18, 0x20, 0x15, 0x20 , 0x1C, 0x20, 0x20, 0x20 , 0x26, 0x40, 0x20, 0x20 , 0x2B, 0x20, 0x26, 0x20 , 0x20, 0x20, 0x30, 0x80 , 0xFF, 0x20, 0x20, 0x1C , 0x10, 0x18, 0x10, 0x20 , 0x20, 0x26, 0x20, 0x2B , 0x20, 0x30, 0x20, 0x2B , 0x40, 0x20, 0x20, 0x1C , 0x10, 0x18, 0x10, 0x20 , 0x20, 0x26, 0x20, 0x2B , 0x20, 0x30, 0x20, 0x2B , 0x40, 0x20, 0x30, 0x1C , 0x10, 0x18, 0x20, 0x15 , 0x20, 0x1C, 0x20, 0x20 , 0x20, 0x26, 0x40, 0x20 , 0x20, 0x2B, 0x20, 0x26 , 0x20, 0x20, 0x20, 0x30 , 0x80, 0x20, 0x30, 0x1C , 0x10, 0x20, 0x10, 0x1C , 0x10, 0x20, 0x20, 0x26 , 0x20, 0x2B, 0x20, 0x30 , 0x20, 0x2B, 0x40, 0x20 , 0x15, 0x1F, 0x05, 0x20 , 0x10, 0x1C, 0x10, 0x20 , 0x20, 0x26, 0x20, 0x2B , 0x20, 0x30, 0x20, 0x2B , 0x40, 0x20, 0x30, 0x1C , 0x10, 0x18, 0x20, 0x15 , 0x20, 0x1C, 0x20, 0x20 , 0x20, 0x26, 0x40, 0x20 , 0x20, 0x2B, 0x20, 0x26 , 0x20, 0x20, 0x20, 0x30 , 0x30, 0x20, 0x30, 0x1C , 0x10, 0x18, 0x40, 0x1C , 0x20, 0x20, 0x20, 0x26 , 0x40, 0x13, 0x60, 0x18 , 0x20, 0x15, 0x40, 0x13 , 0x40, 0x18, 0x80, 0x00 }; void int0() interrupt 1 //采用中断0 控制节拍 { TH0=0xd8; TL0=0xef; n--; } void delay (unsigned char m) //控制频率延时 { unsigned i=3*m; while(--i); } void delayms(unsigned char a) //豪秒延时子程序 { while(--a); //采用while(--a) 不要采用while(a--); 各位可编译一下看看汇编结果就知道了! } void main() { unsigned char p,m; //m为频率常数变量 unsigned char i=0; //TMOD&=0x0f; TMOD|=0x01; TH0=0xd8; TL0=0xef; IE=0x82; while(1) { p=music_tab; if(p==0x00) { i=0, delayms(1000);} //如果碰到结束符,延时1秒,回到开始再来一遍 else if(p==0xff) { i=i+1;delayms(100),TR0=0;} //若碰到休止符,延时100ms,继续取下一音符 else {m=music_tab[i++], n=music_tab[i++];} //取频率常数 和 节拍常数 TR0=1; //开定时器1 while(n!=0) Beep=~Beep,delay(m); //等待节拍完成, 通过P1口输出音频(可多声道哦!) TR0=0; //关定时器1 } } |
|
相关推荐
10个回答
|
|
看看顺便学习一下
|
|
|
|
取谱软件的编解码方式不一样造成的吧
|
|
|
|
看看顺便学习一下
|
|
|
|
是这个原因吗?那样怎么改进呢?求指教。。。我之前想的是音乐有不同的调子和节拍,但是不知道如何设置定时器来改变这些参数。 |
|
|
|
//格式为: 频率常数, 节拍常数, 频率常数, 节拍常数, //求解释,望大家能帮帮忙。 这一句就是关键,以0x18的频率发音0x30的时间,再以0x1C的频率发音0x10的时间,再以0x20的频率发音0x40的时间,你明白规律了吗? |
|
|
|
明白规律 我已经弄清楚了不同的音符对应的频率了(十六进制的那个)但是怎么知道发音的时间呢?怎么算出十六进制的来呢? |
|
|
|
|
|
|
|
while(n!=0) Beep=~Beep,delay(m); //等待节拍完成, 通过P1口输出音频(可多声道哦!) 这一句是和节拍有关的,只要n不等于0,这个节拍就没完成,而前面的中断函数每中断一次把n减1,可以根据中断算出节拍的实际时间,至于发音时间应该是多长,恐怕这得问一下音乐家了 |
|
|
|
主函数里面的p变量是什么含义呢?根据p=music_tab;语句,似乎p应该是指针变量,指向music_tab的首地址。那么在下面的if语句中调用的时候,就应该是*p。不知道是否正确,仅供参考。
|
|
|
|
谢谢你的解答。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
《DNESP32S3使用指南-IDF版_V1.6》第三十章 DHT11数字温湿度传感器
522 浏览 0 评论
656 浏览 0 评论
【敏矽微ME32G070开发板免费体验】之原厂2812测试例程解析
978 浏览 0 评论
1042 浏览 2 评论
《DNESP32S3使用指南-IDF版_V1.6》第二十六章 INFRARED_RECEPTION实验
735 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
12044 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-27 10:13 , Processed in 0.836820 second(s), Total 87, Slave 71 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号