这个小程序仍然是定时器的运用,比较简单,具体的地方都在注释中注明了,参考注释。
- /*********************************************
- 程序功能:MCU控制蜂鸣器演奏歌曲《祝你平安》
- ----------------------------------------------
- 拨码开关设置:将BUZZER位拨至ON,其余位拨至OFF
- 测试说明:聆听蜂鸣器“唱出”的乐曲
-
- 既然是演奏乐曲对于一个音符应该包括两个部分
- 一是声调 二是持续时间,在这个程序中声调是用简单的
- 延时-电平翻转来实现的,改变了延时的时间就改变了
- 声调,而时间是通过计数比较来实现的,当计数值相等时
- 就跳出循环演奏下一个音符。
- *********************************************/
- #include
-
- typedef unsigned char uchar;
-
- #include "music.h"
-
- #define Buzzer BIT7
- #define Buzzer_Port P6OUT
- #define Buzzer_DIR P6DIR
-
- uchar counter;
- void Play_Song(void);
-
- /***************主函数****************/
- void main(void)
- {
- uchar i;
-
- /*下面六行程序关闭所有的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; //关闭看门狗
- /*------选择系统主时钟为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();
- //循环演奏歌曲
- while(1)
- {
- Play_Song();
- }
- }
-
- /*******************************************
- 函数名称:TimerA_ISR
- 功 能:定时器A的中断服务函数
- 参 数:无
- 返回值 :无
- ********************************************/
- #pragma vector = TIMERA0_VECTOR
- __interrupt void TimerA_ISR(void)
- {
- counter++;
- }
- /*******************************************
- 函数名称:Delay_Nms
- 功 能:延时N个ms的函数 ps:不知道这个地方怎么算出来的是延时毫秒
- 参 数:n--延时长度
- 返回值 :无
- ********************************************/
- void Delay_Nms(uchar n)
- {
- uchar i,j;
-
- for( i = 0;i < n; i++ )
- {
- for( j = 0;j < 3;j++ )
- _NOP();
- }
- }
- /*******************************************
- 函数名称:Play_Song
- 功 能:播放《祝你平安》的乐曲
- 参 数:无
- 返回值 :无
- ********************************************/
- void Play_Song(void)
- {
- uchar Temp1,Temp2;
- uchar addr = 0;
-
- counter = 0; //中断计数器清0
- while(1)
- {
- Temp1 = SONG[addr++];
- if ( Temp1 == 0xFF ) //休止符
- {
- TACTL &=~MC_1; //停止计数
- Delay_Nms(100);
- }
- else if ( Temp1 == 0x00 ) //歌曲结束符
- {
- return;
- }
- else
- {
- Temp2 = SONG[addr++];
- TACTL |=MC_1; //开始计数
- while(1)
- {
- Buzzer_Port ^= Buzzer;//电平取反
- Delay_Nms(Temp1);//Temp1的值决定了延时的长短,也决定了声音的频率
- if ( Temp2 == counter )//决定了音调持续的时间,计数时间到时就跳出循环演奏下一个。
- {
- counter = 0;
- break;
- }
- }
- }
- }
- }
|