赞
踩
搬一篇文章过来,2009年本人写在网易博客上的,现在网页博客已经关了,先挪过来,避免以后不在了。
关于程序的补充说明:
1、两个定时器的作用,及中断优先级的问题。
(1)定时器0——是一直输出方波,直到音乐结束;优先级最高;
(2)定时器1——控制输出方波的时间。当输出一个音符的时间到达规定长度时,改变定时器0的计数值,也就是改变方波频率,输出下一个音符;
2、系统的时钟频率
注意下系统的时钟频率;
/***********************************************************
文件名: MusicPlay.c
描 述:
单片机演奏音乐;
程序结构描述:
main()函数在初始化后即进入while(1);功能主要在两个中断中完成;
定时器0中断主要输出一定频率的方波,初始值在于FreqTab中获取;
定时器1中断完成音长的控制,在完成特定音符的音长后读取下一个
音符,并且更新定时器0的初始设置值;
补充音乐知识:
音乐主要由音频和音长;
换个角度,
要输出一首音乐即用一个IO口输出特定时间长度和频率的方波
|<------- 音长1(节拍) --------->| <---- 音长2(节拍)------>| ...
__ __ __ __ __ ___ ___ ___
|__| |__| |__| |__| |__| |___| |___| |___| |___
| 音符1(频率1) | 音符2(频率2) | ...
Email:xiesx1985@126.com
by xiesx,2008.12.26
**************************************************************/
- #include <reg51.h>
-
- unsigned char volatile FlagBeat; // 基本节拍单位计数变量
- unsigned int volatile FreqTemp;
- unsigned char volatile music_temp; //暂时存放从MusicTable数组中读出的变量
- unsigned char volatile beat; //
- unsigned char volatile freq; //简谱码对应T值数组的下标
- unsigned char volatile *pmusic;
-
- sbit Pin_Buzzer=P1^0;
-
- unsigned int code FreqTab[]={ //简谱对应的简谱码、T值
- 65535,
- 64260,64400,64524,64580,64684,
- 64777,64820,64898,64968,65030,
- 65058,65110,65157,65178,65217
- };
-
- unsigned char code MusicTable[]={//音符节拍码
- 0x82,0x01,0x81,0x94,0x84,
- 0xb4,0xa4,0x04,
- 0x82,0x01,0x81,0x94,0x84,
- 0xc4,0xb4,0x04,
-
- 0x82,0x01,0x81,0xf4,0xd4,
- 0xb4,0xa4,0x94,
- 0xe2,0x01,0xe1,0xd4,0xb4,
- 0xc4,0xb4,0x04,
-
- 0x82,0x01,0x81,0x94,0x84,
- 0xb4,0xa4,0x04,
- 0x82,0x01,0x81,0x94,0x84,
- 0xc4,0xb4,0x04,
-
- 0x82,0x01,0x81,0xf4,0xd4,
- 0xb4,0xa4,0x94,
- 0xe2,0x01,0xe1,0xd4,0xb4,
- 0xc4,0xb4,0x04,
-
- 0x00
-
- };
-
- //中断优先级最高,产生FreqTab表中对应的频率
- void timer0() interrupt 1 using 0
- {
- TR0=0;
- TL0= FreqTemp;
- TH0= FreqTemp>>8;
- TR0=1;
- Pin_Buzzer=~Pin_Buzzer;
- }
-
- //用于控制音长的定时中断, 每1/4拍变量FlagBeat加1
- //47ms中断一次
- void timer1() interrupt 3 using 1
- {
- FlagBeat++;
- TR1=0;
- TL1=0x68;
- TH1=0x48;
- TR1=1;
- //
- if(*pmusic==0x00)pmusic=MusicTable;
- {
- if(FlagBeat==beat)
- {
- FlagBeat=0;
- music_temp=*pmusic;
- beat= music_temp&0x0F; //取得节拍数
- beat=beat*4;
- freq =music_temp>>4; //取得音符编码
- pmusic++;
-
- if(freq==0)TR0=0;
- else
- {
- TR0=0;
- FreqTemp=FreqTab[freq];
- TL0= FreqTemp;
- TH0= FreqTemp>>8;
- TR0=1;
- }
- }
- }
-
- }
- void main()
- {
-
- pmusic=MusicTable;
- beat=1;
- FlagBeat=0;
- TMOD=0x11;//定时器0,1都工作16位计数方式
- ET0=1; //允许定时器0溢出中断;
- ET1=1; //允许定时器1溢出中断
- EA=1;
- TL1=0xF0;
- TH1=0xFF;
- TR1=1;
-
- while(1)
- {
-
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。