中国指股网 > 股权 > 内容页

第9章-步进电机与蜂鸣器(下:蜂鸣器播放音乐)

2023-08-28 12:55:22 来源:哔哩哔哩


(资料图片仅供参考)

无源蜂鸣器发声;需要方波,可以控制频率

挺绕的,一方面要控制频率,一方面要控制发声时间

有源蜂鸣器:给电就响,控制简单

老师的只能看懂一半,

用自己的理解改写了一半,成功

//用T0播放频率,T0控制时间的方式#include <>typedef unsigned char u8;typedef unsigned int  u16;typedef unsigned long u32;typedef signed char i8;typedef signed int  i16;typedef signed long i32;sbit BUZZ = P1^6;  //蜂鸣器控制引脚u16 code Frequ[] = {  //中音1-7和高音1-7对应频率列表    523,  587,  659,  698,  784,  880,  988,  //中音1-7    1047, 1175, 1319, 1397, 1568, 1760, 1976  //高音1-7};u16 code Frequ2Reload[] = { //中音1-7和高音1-7对应的定时器重载值    65536 - (11059200/12) / (523*2),  //中音1    65536 - (11059200/12) / (587*2),  //2    65536 - (11059200/12) / (659*2),  //3    65536 - (11059200/12) / (698*2),  //4    65536 - (11059200/12) / (784*2),  //5    65536 - (11059200/12) / (880*2),  //6    65536 - (11059200/12) / (988*2),  //7    65536 - (11059200/12) / (1047*2), //高音1    65536 - (11059200/12) / (1175*2), //2    65536 - (11059200/12) / (1319*2), //3    65536 - (11059200/12) / (1397*2), //4    65536 - (11059200/12) / (1568*2), //5    65536 - (11059200/12) / (1760*2), //6    65536 - (11059200/12) / (1976*2), //7};//两只老虎音符表u8 code TwoTigerYin[] = {    1,   2,   3, 1,    1,   2,   3, 1,   3, 4, 5,   3, 4, 5,    5,6, 5,4, 3, 1,    5,6, 5,4, 3, 1,   1, 5, 1,   1, 5, 1,};//两只老虎节拍表,4表示一拍,1就是1/4拍,8就是2拍u8 code TwoTigerYinLen[] = {    4,   4,   4, 4,    4,   4,   4, 4,   4, 4, 8,   4, 4, 8,    3,1, 3,1, 4, 4,    3,1, 3,1, 4, 4,   4, 4, 8,   4, 4, 8,};//1/4拍约500ms,1/16拍=125ms,调节播放速度u32 pai1p16=125;u8 TH0RL = 0x00;  //T0重载值的高字节u8 TL0RL = 0x00;  //T0重载值的低字节u16 beepCnt=0;u16 silentCnt=0;bit beepBusy=0;/* 两只老虎乐曲播放函数 */void PlayTwoTiger(){    u8 i;    u8 yin;    u16 yinReload;    u8 yinChangN;    u16 yinChang;    u16 yinHz;    u8 cnt=sizeof(TwoTigerYinLen);        for(i=0;i<cnt;i++)    {        //取出音符,转换成频率,转换成T0的初值,设置T0,        yin=TwoTigerYin[i];        yinReload=Frequ2Reload[yin-1];        TH0RL=(u8)(yinReload>>8);        TL0RL=(u8)(yinReload);        TH0=TH0RL;        TL0=TL0RL;                //计算播放时间,取出音符长度,转化成进入中断的次数,与频率有关        //音长的进行播放,静音        yinChangN=TwoTigerYinLen[i];        yinHz=Frequ[yin-1];//取出频率,参与进入中断次数的计算        yinChang=(yinChangN*pai1p16*yinHz*2/1000);//要用i32,否则高位丢失        silentCnt=yinChang>>2;     //音长的进行播放,静音        beepCnt=yinChang-silentCnt;//音长的进行播放,静音                //开启T0,去播放改频率(音)        ET0=TR0=1;        beepBusy=1;                while(beepBusy==1);//等待这个音播放完毕,切换下一个音    }    }int main(void){    u16 i;        EA = 1;       //使能全局中断    TMOD = 0x01;  //配置T0工作在模式1        while (1)    {        PlayTwoTiger();  //播放乐曲--两支老虎        for (i=0; i<40000; i++);  //停止一段时间    }}/* T0中断服务函数,用于控制蜂鸣器发声 */void InterruptTimer0() interrupt 1{    TH0 = TH0RL;   //重新加载重载值    TL0 = TL0RL;    if(beepCnt)    {        beepCnt--;        BUZZ=~BUZZ;    }else if(silentCnt)    {        silentCnt--;        BUZZ=1;    }    else    {        beepBusy=0;        ET0=TR0=0;    }}//用T0播放频率,用T1控制时间的方式#include <>typedef unsigned char u8;typedef unsigned int  u16;typedef unsigned long u32;typedef signed char i8;typedef signed int  i16;typedef signed long i32;sbit BUZZ = P1^6;  //蜂鸣器控制引脚u16 code Frequ[] = {  //中音1-7和高音1-7对应频率列表    523,  587,  659,  698,  784,  880,  988,  //中音1-7    1047, 1175, 1319, 1397, 1568, 1760, 1976  //高音1-7};u16 code Frequ2Reload[] = { //中音1-7和高音1-7对应的定时器重载值    65536 - (11059200/12) / (523*2),  //中音1    65536 - (11059200/12) / (587*2),  //2    65536 - (11059200/12) / (659*2),  //3    65536 - (11059200/12) / (698*2),  //4    65536 - (11059200/12) / (784*2),  //5    65536 - (11059200/12) / (880*2),  //6    65536 - (11059200/12) / (988*2),  //7    65536 - (11059200/12) / (1047*2), //高音1    65536 - (11059200/12) / (1175*2), //2    65536 - (11059200/12) / (1319*2), //3    65536 - (11059200/12) / (1397*2), //4    65536 - (11059200/12) / (1568*2), //5    65536 - (11059200/12) / (1760*2), //6    65536 - (11059200/12) / (1976*2), //7};//两只老虎音符表,,,该音用来查询频率,T0的初值u8 code TwoTigerYin[] = {    1,   2,   3, 1,    1,   2,   3, 1,   3, 4, 5,   3, 4, 5,    5,6, 5,4, 3, 1,    5,6, 5,4, 3, 1,   1, 5, 1,   1, 5, 1,};//两只老虎节拍表,4表示一拍,1就是1/4拍,8就是2拍,,该拍用来计算播放时长u8 code TwoTigerYinLen[] = {    4,   4,   4, 4,    4,   4,   4, 4,   4, 4, 8,   4, 4, 8,    3,1, 3,1, 4, 4,    3,1, 3,1, 4, 4,   4, 4, 8,   4, 4, 8,};//1/4拍约500ms,1/16拍=125ms,调节播放速度u32 pai1p16=125; //1/16拍=125ms,u8 TH0RL = 0x00;  //T0重载值的高字节u8 TL0RL = 0x00;  //T0重载值的低字节u16 beepCnt=0; //每个音的发声时长u16 silentCnt=0; //每个音的静音时长bit beepBusy=0; //0=一个音播放完毕,可以切换下一个;1=一个音正在播放,不能切换下一个/* 两只老虎乐曲播放函数 */void PlayTwoTiger(){    u8 i;    u8 yin;    u16 yinReload;    u8 yinChangN;    u16 yinChang;    u8 cnt=sizeof(TwoTigerYinLen);        for(i=0;i<cnt;i++)    {        //取出音符,转换成频率,转换成T0的初值,设置T0,        yin=TwoTigerYin[i];//取出音符        yinReload=Frequ2Reload[yin-1];//根据音符查询到T0初值        TH0RL=(u8)(yinReload>>8);        TL0RL=(u8)(yinReload);        //T0负责发出指定频率的声音        TH0=TH0RL;        TL0=TL0RL;                //计算播放时间,取出音符长度,转换成时间ms,再转化成进入中断的次数        //音长的进行播放,静音        yinChangN=TwoTigerYinLen[i];//取出(1/16拍)的倍数        yinChang=(yinChangN*pai1p16*4);//,所以乘4     要用i32,否则高位丢失        silentCnt=yinChang>>2;     //音长的进行播放,静音        beepCnt=yinChang-silentCnt;//音长的进行播放,静音                //开启T0,去播放改频率(音),,开启T1去控制播放时间        ET0=TR0=1;        TH1=TL1=0x1A; //方式2自动重装,一次中断        ET1=TR1=1;        beepBusy=1;//控制播放下一个音                while(beepBusy==1);//等待这个音播放完毕,切换下一个音    }    }int main(void){    u16 i;        EA = 1;       //使能全局中断    TMOD = 0x21;  //配置T0工作在模式1; T2工作在方式2, 进入一次    PT0=1;//T0优先级高,效果好    while (1)    {        PlayTwoTiger();  //播放乐曲--两支老虎        for (i=0; i<40000; i++);  //停止一段时间    }}/* T0中断服务函数,用于控制蜂鸣器发声频率 */void Timer0_ISR() interrupt 1{    TH0 = TH0RL;   //重新加载重载值    TL0 = TL0RL;    BUZZ=~BUZZ;}/* T1中断服务函数,用于控制蜂鸣器发声时间 */void Timer1_ISR(void) interrupt 3{    if(beepCnt)//发声时间段    {        beepCnt--;    }    else if(silentCnt)//禁止发声时间段    {        silentCnt--;        TR0=0;    }    else //这个音播放完毕    {        beepBusy=0;        TR1=0;    }}

上一篇 下一篇
x 广告
推荐阅读