找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4263|回复: 4
收起左侧

请问蜂鸣器音乐程序如何延长单次循环时间?

[复制链接]
ID:163118 发表于 2017-2-7 13:44 | 显示全部楼层 |阅读模式
7黑币
我把一首歌的歌谱翻译为代码,在ISIS仿真过程中,每当播放到快结束的地方就从头开始了,后面的就没有了,如此循环。经过多次改动试验,我推测是单次循环时间达到上限,请问如何延长单次循环时间,从而实现歌曲的完整播放?(代码见下)(最后有仿真图片)

#include <reg52.h>
#define uchar unsigned char
#define uint  unsigned int
sbit fm=P3^4;                                        //蜂鸣器控制端口        
uchar timeh,timel;                                //用于存放定时器的高8位和低8位
uchar code zbjbxf[]={                                //定义《快乐成长》的简谱数组
0xB3,0x91,0xC2,0xB6,0x83,0x61,0x92,0x86,0x62,0x61,0x61,0x62,0x82,0x81,0x81,0x82,0x92,0x82,0x42,0x56,        //歌曲第一段(与歌谱每行对应,至反复记号处)
0x62,0x02,0x42,0x64,0x82,0xB2,0xA2,0x82,0x96,0x94,0xB1,0x91,0x84,0x91,0x81,0x12,0x82,0x51,0x61,0x4A,
0x62,0x84,0x42,0x93,0x81,0x61,0x51,0x42,0x52,0x62,0x14,0x12,0x23,0x11,0x81,0x91,0x82,0x02,0x61,0x61,
0x92,0x82,0x42,0x56,0x62,0x02,0x42,0x64,0x41,0x81,0xB4,0xA2,0x83,0x91,0x82,0x53,0x41,0x51,0x61,0x26,
0x44,0x72,0x94,0x91,0x91,0x84,0x82,0x94,0x62,0x92,0x82,0x32,0x4A,0x81,0x61,0xB2,0xB1,0x91,0xC2,
0xB6,0x82,0x81,0x61,0x92,0x86,0x92,0xB2,0xB2,0xC2,0xB3,0x91,0x62,0x52,0x42,0x12,0x82,0x42,0x56,
0x62,0x02,0x42,0x64,0x82,0xB2,0xA2,0x82,0x96,0x92,0xB3,0x91,0x82,0x92,0x82,0x62,0x52,0x42,0x12,0x82,0x51,0x61,
0x4C,
0xB3,0x91,0xC2,0xB6,0x83,0x61,0x92,0x86,0x62,0x61,0x61,0x62,0x82,0x81,0x81,0x82,0x92,0x82,0x42,0x56,        //歌曲第二段(与歌谱每行对应)
0x62,0x02,0x42,0x64,0x82,0xB2,0xA2,0x82,0x96,0x94,0xB1,0x91,0x84,0x91,0x81,0x12,0x82,0x51,0x61,0x4A,
0x62,0x84,0x42,0x93,0x81,0x61,0x51,0x42,0x52,0x62,0x14,0x12,0x23,0x11,0x92,0x82,0x02,0x61,0x61,               
0x92,0x82,0x42,0x56,0x62,0x02,0x42,0x64,0x41,0x81,0xB4,0xA2,0x83,0x91,0x82,0x93,0x81,0x81,0x91,0x66,
0x44,0x72,0x94,0x91,0x91,0x84,0x82,0x94,0x62,0x92,0x82,0x32,0x4A,0x81,0x61,0xB2,0xB1,0x91,0xC2,
0xB6,0x82,0x81,0x61,0x92,0x86,0x92,0xB2,0xB2,0xC2,0xB3,0x91,0x62,0x52,0x42,0x12,0x82,0x42,0x56,
0x62,0x02,0x42,0x64,0x82,0xB2,0xA2,0x82,0x96,0x92,0xB3,0x91,0x82,0x92,0x82,0x62,0x52,0x42,0x12,0x82,0x51,0x61,
0x46,0x62,0x02,0x42,0x64,0x82,0xB2,0xA2,0x82,0x9C,
0x92,0xB3,0x91,0x82,0x92,0x82,0x62,0x52,0x42,0x14,0x82,0x94,0x82,0xBC,0xff};
uchar code chuzhi[]={                           //适合12M的晶振定时器初值表,高低8位分开
         0xff,0xff,                                //占位
         0xFB,0xE9,                                //D调低音5-中音4        
         0xFC,0x5B,        
         0xFC,0xBD,        
         0xFC,0xED,        
         0xFD,0x43,        
         0xFD,0x8E,
         0xFD,0xB3,         
         0xFD,0xF3,                                //D调中音5-高音4
         0xFE,0x2D,
         0xFE,0x5E,        
         0xFE,0x76,
         0xFE,0xA1,
         0xFE,0xD0,
         0xFE,0xD9,
         };
void timer0() interrupt 1{                         //定时器0中断服务程序
        TH0=timeh;                                //将timeh赋给计时器的高8位
        TL0=timel;                                 //将timel赋给计时器的低8位

        fm=~fm;                                 //定时器每次到时将蜂鸣器反相
}
void delay(uint z){                                //延时238ms,即八分音符
        uint y;
        for(z;z>0;z--)
                 for(y=27406;y>0;y--);                //大致时间
}
void delay1(uint z){                                //音符间适当延时
        uint y;
        for(z;z>0;z--)
                 for(y=162;y>0;y--);                //大致时间
}
void main(){
        uint temp;                                //存放简谱数组中的每一个音符的临时变量
        uchar i=0;        
        uchar jp;                                //jp用于取出temp中的高8位和低8位
        TMOD=0x01;                                //设置定时器T0工作于方式1
        IE=0x82;                                  //允许T0中断
        while(1){
                temp=zbjbxf;
           if(temp==0xff)
                        break;        
                jp=temp/16;                         //取数的高4位,音频数值
                if(jp!=0){
                        timeh=chuzhi[jp*2];        //构造定时器初值高8位
                        timel=chuzhi[jp*2+1];         //构造定时器初值低8位
                        TR0=1;                          //开定时器
                }else{
                        TR0=0;                          //关定时器
                        fm=1;                          //关蜂鸣器
                }
                delay(temp%16);                 //取数的低4位,节拍(音符总时延)
                TR0=0;                                 //唱完一个音停5ms
                fm=1;
                delay1(5);
                TR0=1;
                i++;
        }
        TR0=0;                                        //关定时器
        fm=1;                                        //关蜂鸣器
}

仿真图片如下:
QQ截图20170203184430.jpg

回复

使用道具 举报

ID:163775 发表于 2017-2-7 15:43 | 显示全部楼层
我觉得你可以在循环的最后加上延迟函数,延迟长一点,应该会有用。
回复

使用道具 举报

ID:111634 发表于 2017-2-7 18:45 | 显示全部楼层
本帖最后由 zl2168 于 2017-2-7 18:47 编辑

定时器控制播放生日快乐歌


Proteus仿真一下,确认有效。
实例75 定时器控制播放生日快乐歌.rar (26.96 KB, 下载次数: 12)
回复

使用道具 举报

ID:163118 发表于 2017-2-9 12:17 | 显示全部楼层
zk159669 发表于 2017-2-7 15:43
我觉得你可以在循环的最后加上延迟函数,延迟长一点,应该会有用。

我不知道具体怎么弄,请赐教!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表