這個小程序仍然是定時器的運用,比較簡單,具體的地方都在注釋中注明了,參考注釋。
/*********************************************
程序功能:MCU控制蜂鳴器演奏歌曲《祝你平安》
----------------------------------------------
撥碼開關設置:將BUZZER位撥至ON,其余位撥至OFF
測試說明:聆聽蜂鳴器“唱出”的樂曲
既然是演奏樂曲對于一個音符應該包括兩個部分
一是聲調二是持續(xù)時間,在這個程序中聲調是用簡單的
延時-電平翻轉來實現(xiàn)的,改變了延時的時間就改變了
聲調,而時間是通過計數(shù)比較來實現(xiàn)的,當計數(shù)值相等時
就跳出循環(huán)演奏下一個音符。
*********************************************/
#include
typedefunsignedcharuchar;
#include"music.h"
#defineBuzzerBIT7
#defineBuzzer_PortP6OUT
#defineBuzzer_DIRP6DIR
ucharcounter;
voidPlay_Song(void);
/***************主函數(shù)****************/
voidmain(void)
{
uchari;
/*下面六行程序關閉所有的IO口*/
P1DIR=0XFF;P1OUT=0XFF;
P2DIR=0XFF;P2OUT=0XFF;
P3DIR=0XFF;P3OUT=0XFF;
P4DIR=0XFF;P4OUT=0XFF;
P5DIR=0XFF;P5OUT=0XFF;
P6DIR=0XFF;P6OUT=0XFF;
P6DIR|=BIT2;P6OUT|=BIT2;//關閉電平轉換
WDTCTL=WDTPW+WDTHOLD;//關閉看門狗
/*------選擇系統(tǒng)主時鐘為8MHz-------*/
BCSCTL1&=~XT2OFF;//打開XT2高頻晶體振蕩器
do
{
IFG1&=~OFIFG;//清除晶振失敗標志
for(i=0xFF;i>0;i--);//等待8MHz晶體起振
}
while((IFG1&OFIFG));//晶振失效標志仍然存在?
BCSCTL2|=SELM_2+SELS;//主時鐘和從時鐘都選擇高頻晶振
//設置定時器A每10ms中斷一次
CCTL0=CCIE;
CCR0=10000;//改變這個值就改變了演奏的速度
TACTL|=TASSEL_2+ID_3;
//設置控制蜂鳴器的IO方向為輸出
Buzzer_DIR|=Buzzer;
//打開全局中斷
_EINT();
//循環(huán)演奏歌曲
while(1)
{
Play_Song();
}
}
/*******************************************
函數(shù)名稱:TimerA_ISR
功能:定時器A的中斷服務函數(shù)
參數(shù):無
返回值:無
********************************************/
#pragmavector=TIMERA0_VECTOR
__interruptvoidTimerA_ISR(void)
{
counter++;
}
/*******************************************
函數(shù)名稱:Delay_Nms
功能:延時N個ms的函數(shù)ps:不知道這個地方怎么算出來的是延時毫秒
參數(shù):n--延時長度
返回值:無
********************************************/
voidDelay_Nms(ucharn)
{
uchari,j;
for(i=0;i
{
for(j=0;j<3;j++)
_NOP();
}
}
/*******************************************
函數(shù)名稱:Play_Song
功能:播放《祝你平安》的樂曲
參數(shù):無
返回值:無
********************************************/
voidPlay_Song(void)
{
ucharTemp1,Temp2;
ucharaddr=0;
counter=0;//中斷計數(shù)器清0
while(1)
{
Temp1=SONG[addr++];
if(Temp1==0xFF)//休止符
{
TACTL&=~MC_1;//停止計數(shù)
Delay_Nms(100);
}
elseif(Temp1==0x00)//歌曲結束符
{
return;
}
else
{
Temp2=SONG[addr++];
TACTL|=MC_1;//開始計數(shù)
while(1)
{
Buzzer_Port^=Buzzer;//電平取反
Delay_Nms(Temp1);//Temp1的值決定了延時的長短,也決定了聲音的頻率
if(Temp2==counter)//決定了音調持續(xù)的時間,計數(shù)時間到時就跳出循環(huán)演奏下一個。
{
counter=0;
break;
}
}
}
}
}