(资料图片仅供参考)
无源蜂鸣器发声;需要方波,可以控制频率
挺绕的,一方面要控制频率,一方面要控制发声时间
有源蜂鸣器:给电就响,控制简单
老师的只能看懂一半,
用自己的理解改写了一半,成功
//用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; }}