单片机音乐演奏程序 经典讲解
单片机演奏一个音符,是通过引脚,周期性的输出一个特定频率的方波。
这就需要单片机,在半个周期内输出低电平、另外半个周期输出高电平,周而复始。
半个周期的时间是多长呢?众所周知,周期为频率的倒数,可以通过音符的频率计算出半周期。
演奏时,要根据音符频率的不同,把对应的、半个周期的定时时间初始值,送入定时器,再由定时器按时输出高低电平。
下面是个网上广泛流传的单片机音乐演奏程序,它可以循环的播放“世上只有妈妈好”这首乐曲。很多人都关心如何修改这个乐曲的内容,但是不知如何入手。
做而论道对这个程序,给出说明,希望对大家有所帮助,以后大家自己就能够编写进去新的乐曲。
在这个程序中,有两个数据表,其中存放了事先算好的、各种音符频率所对应的、半周期的定时时间初始值。
有了这些数据,单片机就可以演奏从低音、中音、高音和超高音,四个八度共28个音符。
演奏乐曲时,就根据音符的不同数值,从半周期数据表中找到定时时间初始值,送入定时器即可控制发音的音调。
比如把表中的0xF2和0x42送到定时器,定时器按照这个初始值来产生中断,输出的方波,人们听起来,这就是低音1。
乐曲的数据,也要写个数据表,程序中以 code unsigned char sszymmh[] 命名。
这个表中每三个数字,说明了一个音符,它们分别代表:
第一个数字是音符的数值1234567之一,代表多来咪发...;
第二个数字是0123之一,代表低音、中音、高音、超高音;
第三个数字是时间长度,以半拍为单位。
乐曲数据表的结尾是三个0。
程序如下:
#include
sbit
unsigned char timer0h, timer0l, time;
//--------------------------------------
//单片机晶振采用11.0592MHz
// 频率-半周期数据表高八位
code unsigned char FREQH[] = {
// 频率-半周期数据表 低八位
code unsigned char FREQL[] = {
//--------------------------------------
//世上只有妈妈好数据表
code unsigned char sszymmh[] = {
6, 2, 3,
//一个音符有三个数字。前为第几个音、中为第几个八度、后为时长(以半拍为单位)。
//6, 2, 3 分别代表:6, 中音, 3个半拍;
//5, 2, 1 分别代表:5, 中音, 1个半拍;
//3, 2, 2 分别代表:3, 中音, 2个半拍;
//5, 2, 2 分别代表:5, 中音, 2个半拍;
//1, 3, 2 分别代表:1, 高音, 2个半拍;
//
6, 2, 4, 3, 2, 2, 5, 2, 1, 6, 2, 1, 5, 2, 2, 3, 2, 2, 1, 2, 1,
6, 1, 1, 5, 2, 1, 3, 2, 1, 2, 2, 4, 2, 2, 3, 3, 2, 1, 5, 2, 2,
5, 2, 1, 6, 2, 1, 3, 2, 2, 2, 2, 2, 1, 2, 4, 5, 2, 3, 3, 2, 1,
2, 2, 1, 1, 2, 1, 6, 1, 1, 1, 2, 1, 5, 1, 6, 0, 0, 0};
//--------------------------------------
void t0int()interrupt1
{
}
//--------------------------------------
void delay(unsigned char t)
{