音乐播放器_源代码

单片机音乐演奏程序设计

——单字节编码方法

1、音乐演奏原理

利用单片机的定时器定时,定时到后对单片机的某个引脚取反产生方波信号,初值不同,方波信号的频率不同,方波信号经过放大后送喇叭发出不同音调的声音。选某个乐谱,将每一个音的音调和音长按照一定的规则进行编码,组成编码数表。然后编写程序,从编码数表中连续读出各个音的编码,根据音调编码获得其频率,再由频率计算出定时器的定时初值,从某个引脚产生出对应频率的方波信号,在喇叭上发出对应频率的声音;再根据音长编码产生延时,从而连续播放出音乐。

2、乐谱单字节编码方法

1)定时器0/1产生各种音的方法

1 为C调的发音频率表,给出了各个音的频率f,可以用定时器/计数器,定时产生对应频率的方波信号,将方波信号送给喇叭,便可使喇叭发出同频率的声音。定时初值x与发声频率f的关系如下:

由公式  t=(2 n  x)×Tmc

式中 t=T/2 T=1/f Tmc=12/fosc

n16表示用模式1定时,Tmc为机器周期,fosc为晶振频率,因此初值x为:

x65536(1/f/2)×fosc/12

扫描二维码关注公众号,回复: 2689375 查看本文章

如果fosc=12Hzx=65536-500000/f

1  C音调发音频率表

C   调

5

6

7

1

2

3

4

5

6

7

频率f(Hz)

196

220

247

262

294

330

349

392

440

494

523

588

660

其它各音的发声频率如图1所示。

2乐谱单字节编码方法

字节的高4位表示谱的音,低4位表示音的长短(单字节法最多只能表示15个音)。

表示方法:一个乐谱中的最低音用1表示,次低音用2表示……,依次类推,休止符用0表示。

音长短的表示方法:一个乐谱中的最短音用1表示,其它音的长度都是它的整数倍,是它的几倍用几表示。

3)乐谱单字节编码举例

乐谱:  3  5    6 i 6 5  |   2 ·  3   6  5  |   1   —  |  1   0  ||

编码:该段乐谱的最低音5编码1,其它音67……依次编码为23……,休止符用0表示。其编码对应关系如表2所示。

2  编码与音对应关系

音 名

0

5

6

7

1

2

3

4

5

6

7

编 码

0

1

2

3

4

5

6

7

8

9

a

b

c

d

编码与音名的换算:

音长编码:由于该段乐谱的最短音是1/4拍,因此将1/4拍编码为1,其音长编码如下:

1表示1/4拍、 2表示2/4拍、

3表示3/4拍、 4表示1拍、

6表示1.5拍、 8表示2拍、

c表示3……

上面一段乐谱的编码为: 0x620x820x910xb10x910x810x530x610x220x120x4c0x040。(最后的0表示乐谱结束)

节拍时间计算:

设某歌曲的演奏速度为p/分钟,则每拍的时间间隔为:

分钟/p=60000毫秒/p

若某歌曲的最短音为1/4拍,对应的延时为15000毫秒/p,则15000毫秒/p该歌曲的基本延时单位。

p=100,即每分钟100拍,则一个基本延时单位(1/4拍)的时间长度为150ms

3、程序设计方法

需要编写以下4个函数建立歌曲编码表和频率表。

1)建立歌曲编码表和频率表

乐谱编码数组mus[ ]

各音频率数组freq[ ]

2主函数

主函数主要是对定时器、中断做初始化设置。

3)音乐演奏函数

顺序从歌谱编码数组mus[ ]中读取数据,分离出高4位和低4位。用高4位读取数组freq[ ]的频率值,然后根据定时器初值与频率的关系,计算出定时初值x;用低4位控制发声延时,以上面所述的“15000毫秒/m”为基本延时单位,以低4位为倍数控制发声时间。

4)延时函数

参考教材P16,其中添加1行:

x=x*150;660

5定时器中断函数

4定时器2产生各种音的方法

对于定时器2,发声频率f与单片机振荡频率fosc的关系为:

f=fosc/(2 16  x)/4 2 16 x= fosc/f/4 65536x= fosc/f/4

因此初值x为:

x65536fosc/f/4

如果fosc=12Hzx=655363000000/f

音乐演奏程序流程

 

读取第i个音mus[i++]编码

mus[i]0结束

分离出高低4位给highlow

读取freq[high]得到发声频率f

f计算出定时初值x

x的高低8位分别送给全局变量xhxl及计数器THxTLx

开定时器TxTRx=1

调用延时函数delay(low)

关定时器TxTRx=0

 源代码:

music.h

/*
* Copyrite (c) 2018, 单片机与嵌入式系统工作室
* All Rights Reserved
*
* File Name :music.h(举例)
* File Description :music .h file
*
* Current Version: 1.1
* Author : 徐子航
* Finish Time : 2018.5.13
*
* Earlier Version :
* Author :
* Finish Time :
*/

#ifndef _MUSIC_H
#define _MUSIC_H

#include <reg51.h>

/*------------------------------------------------------------------*-
Custom type
-*------------------------------------------------------------------*/
typedef unsigned char tByte;
typedef unsigned int tWord;
typedef unsigned long tlong;


/*------------------------------------------------------------------*-
Global variable declaration
-*------------------------------------------------------------------*/
extern tByte  high ; //高4位
extern tByte low ;
extern tWord pos_flag ;//位置指向
extern tWord x;  //定时器的初值


/*------------------------------------------------------------------*-
speaker pin
-*------------------------------------------------------------------*/
sbit speaker = P1^6;


/*------------------------------------------------------------------*-
Global function declaration
-*------------------------------------------------------------------*/
void Delay_Ms(tWord x);
void TIME0_Init();
void Play_Music();
	
#endif

music.c

/*
* Copyrite (c) 2018, 单片机与嵌入式系统工作室
* All Rights Reserved
*
* File Name :music.c(举例)
* File Description :小白杨
*
* Current Version: 1.1
* Author : 徐子航
* Finish Time : 2018.5.13
*
* Earlier Version :
* Author :
* Finish Time :
*/

#include <music.h>


/*------------------------------------------------------------------*-
Music simple spectral coding table. code type not change 
-*------------------------------------------------------------------*/
tByte code mus[] = {0x83,0x61,0x52,0x52,0x61, 0x51,0x31,0x21,0x14,0x33
                   ,0x51,0x81,0x91,0x61,0x51, 0x54,0x54,0x81,0x91,0x61
                   ,0x51,0x63,0x81,0x62,0x51, 0x61,0x34,0x52,0x61,0x61
                   ,0x51,0x31,0x31,0x21,0x24, 0x24,0x33,0x51,0x51,0x61
                   ,0x51,0x31,0x22,0x14,0x11, 0x21,0x33,0x51,0x81,0x91
                   ,0x61,0x51,0x62,0x61,0x51, 0x34,0x81,0x91,0x61,0x51
                   ,0x63,0x81,0x62,0x51,0x31, 0x24,0x00};        //小白杨乐谱编码表

tWord code freq[] = {0,362,294,330,349,392,440,494,523,588,660};    //频率编码表


/*------------------------------------------------------------------*-
Global variable definition
-*------------------------------------------------------------------*/
tByte high = 0;
tByte low = 0;
tWord pos_flag = 0;
tWord x = 0;     // X should be defined as tWord type, and tByte will overflow.


//150*xms
void Delay_Ms(tWord x)
{
	tByte i = 0;
	x = x*150;
	while(x--)
		for(i = 0; i< 123; i++);
}


/*------------------------------------------------------------------*-
TIME0 Init to Mode 1
-*------------------------------------------------------------------*/
void TIME0_Init(void)
{
	
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x44;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
    ET0 = 1;
	EA = 1 ;
}


/*------------------------------------------------------------------*-
Play_Music function


Describtion: The encoding value is resolved to the corresponding frequency (high 4 bits) and the beat (low 4 bits).
Start again when the mus array is over.
-*------------------------------------------------------------------*/
void Play_Music(void)
{
	low = mus[pos_flag] & 0x0f;
    high = mus[pos_flag] >> 4;
	
    x = 65536 - 500000/freq[high];
	
	++pos_flag;
	if(pos_flag >= 67)
		 pos_flag = 0;
}


/*------------------------------------------------------------------*-
TIME0 Interrupt handler

Describtion: There will be many interrupts in the corresponding beat of a syllable, 
so the initial value should be reset at the middle.
-*------------------------------------------------------------------*/
void TIME0_IRQHander(void) interrupt 1
{
	
	TL0 = x%256;   //设置定时初值
	TH0 = x/256;   //设置定时初值
	
	speaker = ~speaker;	
}

main.c

/*
* Copyrite (c) 2018, 单片机与嵌入式系统工作室
* All Rights Reserved
*
* File Name :main.c(举例)
* File Description :
*
* Current Version: 1.1
* Author : 徐子航
* Finish Time : 2018.5.13
*
* Earlier Version :
* Author :
* Finish Time :
*/

#include <music.h>

int main()
{
	TIME0_Init();
	
	while(1)
	{
		Play_Music();
		TR0 = 1;		//定时器0开始计时
		Delay_Ms(low);
		TR0 = 0;
	}
	
	return 0;
}

附录1:

猜你喜欢

转载自blog.csdn.net/xv1356027897/article/details/80296842