您的位置 首页 技术

【C51】源码 4 — 喇叭播映【寒蝉鸣泣之时】插曲 You

学单片机到喇叭部分,觉得挺好玩,编写了喇叭播放音乐的程序……BGM取自【寒蝉鸣泣之时】插曲You,简谱由网络提供,感谢作者……先把简…

单片机到喇叭部分,觉得挺好玩,编写了喇叭播映音乐的程序……

BGM 取自【寒蝉鸣泣之时】插曲 You,简谱由网络供给,感谢作者……先把简谱附上:

还有一张克己的“钢琴按键频率散布”,没写那么全,只对应本程序,图如下:

附上源码:(初出茅庐,不免有写的欠好的当地,仅作备份之用,欢迎点拨,喷子退散……)

/*******************************************************************
喇叭播映音乐

BGM 取自【寒蝉鸣泣之时】的插曲 You

缺陷:

1、没有增加调理音量的功用
2、音高、节拍 都要自己提早写好,作业量大
能够改善成:经过解析 midi 文件进行音乐播映
(midi 里面便是音高、节拍信息)
********************************************************************/

#include

sbitSPK = P1^0;// 喇叭输入

/************************************************************************************************************************************
PIANO_F[ ]:是钢琴按键的频率,数组下标对应钢琴按键,如上图所示
例:图上能够看出:8 号键对应钢琴的中心 C,正好是 PIANO_F[8],对应频率为 261.6 Hz
注:PIANO_F[0] 不代表任何按键,为了便利计数,数组下标从 1 开端有意义
*************************************************************************************************************************************/

float codePIANO_F[ ] = {7.63,
130.8, 146.8, 164.8, 174.5, 196.0, 220.0, 247.1,
261.6, 293.6, 329.6, 349.0, 392.0, 440.0, 494.0,
523.2, 587.2, 659.2, 698.3, 784.0, 880.0, 988.0,
1046.4, 1174.4, 1318.4, 1396.8, 1567.7, 1760.0, 1975.3};

/******************************************************************************************************
PITCH[ ]:指的是 音高,对应上图中的按键号
例:中音 do:如图对应 8 号键
高音 do:如图对应 15 号键
优点:假设歌曲播映到了第 i 个音,那么 PITCH[i] 便是对应钢琴上的按键
那么 PIANO_F[ PITCH[i] ] 便是对应的琴键的频率,便利编程运用
注:255 代表 音乐完毕
0 代表 八分休止符
******************************************************************************************************/

unsigned char codePITCH[ ] = {16, 17, 16, 15, 16, 12, 17, 16, 15,
16, 17, 16, 15, 15, 19, 16,
16, 17, 16, 15, 16, 12, 17, 16, 15,
16, 17, 16, 15, 15, 12,
12, 10, 12, 15, 15,
16, 16, 16, 17, 17, 12,
12, 10, 12, 0, 15, 15, 16,
16, 16, 16, 19, 17, 12,
12, 10, 0, 12, 0, 15, 15, 15,
16, 16, 16, 17, 17, 12,
12, 10, 0, 12, 0, 15, 15, 16,
16, 16, 16, 19, 17, 26,
26, 24, 0, 26, 26, 22, 0, 23,
23, 22, 23, 0, 24, 23, 24, 26,
26, 24, 0, 26, 26, 22, 0, 23,
23, 22, 0, 23, 22,
255};

/***************************************************************************************************************
BEAT[ ]:指的是 节拍,数值代表根本节拍的倍数,这儿根本节拍为 十六分音符 长
例:8,代表 8 倍 十六分音符 长,即:二分音符
4,代表 4 倍 十六分音符 长,即:四分音符
2,代表 2 倍 十六分音符 长,即:八分音符
1,代表 1 倍 十六分音符 长,即:十六分音符
6,代表 6 倍 十六分音符 长,即:符点四分音符
***************************************************************************************************************/

unsigned char codeBEAT[ ] = {4, 1, 1, 2, 2, 2, 1, 1, 2, 4, 1, 1, 2, 2, 2, 4,
4, 1, 1, 2, 2, 2, 1, 1, 2, 4, 1, 1, 2, 6, 2,
2, 4, 2, 6, 2, 2, 2, 2, 2, 6, 2,
2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8,
255};

unsigned chartime_h = 0;// 用于向守时器中止程序传递下一步守时信息
unsigned chartime_l = 0;

unsigned inttime = 0;// 依据按键频率,换算出应该守时多长时刻
unsigned chari;

voidInit_Timer0(void);// 初始化 守时器 0
voidDelay(unsigned intt);// 一般延时
voidDelay_ms(unsigned intt);// 适当近似的推迟 t ms

voidmain (void)
{
Init_Timer0();

for(i = 0; PITCH[i] != 255; i++) {// 次序播映,255 为音乐完毕

TR0 = 0;// 关 守时器0

Delay_ms(20);// 延时一段时刻,确保按键与按键之间能分得清楚

/*********************************************************************************************************************
守时时刻 time 的核算:

以 中心 C 为例:频率为 261.6 Hz,便是每秒 261.6 下,倒数便是 每下 1/261.6 s,
换成 us 便是 1,000,000/261.6,每响一次是一个上升沿加一个下降沿,
因而,改换的次数应该是 2 倍,每次改换所花时刻是一半,
即:1,000,000/(2*261.6)
**********************************************************************************************************************/

time = (unsigned int)(1000000 / (2 * PIANO_F[PITCH[i]]));

time_h = (65536 – time) / 256;
time_l = (65536 – time) % 256;

TH0 = time_h;// 守时器赋值
TL0 = time_l;

TR0 = 1;// 开 守时器0

/****************************************************************************************************************
假如音高是 0,阐明是 八分休止符,关守时器,守时器不驱动喇叭,也就没有声音了
****************************************************************************************************************/

if(PITCH[i] == 0) TR0 = 0;

/********************************************************************************************************
适当重要的延时!节拍悉数由它操控,不是很准确,其有用 守时器 1 或许更好
********************************************************************************************************/

Delay_ms(BEAT[i] * 30);
}

TR0 = 0;// 音乐播映完后,关守时器,收尾

/*****************************************************************************************************************
适当重要!没有此句子将导致循环履行 main 函数!

具体评论拜见:http://gaebolg.blog.163.com/blog/static/19826906820122254823928/
*****************************************************************************************************************/

while(1);
}

voidInit_Timer0(void)
{
TMOD = 0x01;// 守时器 0,形式1
EA = 1;// 开 总中止
ET0 = 1;// 开 守时器 0 中止
}

voidTimer0_ISR(void)interrupt1
{
TH0 = time_h;// 重装初值
TL0 = time_l;

SPK = !SPK;// 发生方波,驱动喇叭发声
}

voidDelay(unsigned intt)
{
while(t–);
}

voidDelay_ms(unsigned intt)// 依据测验,能够适当近似的表明 t ms
{
while(t–) {
Delay(245);
Delay(245);
}
}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/jishu/268088.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部