可振动感应切换的电子音乐.docx

上传人:b****4 文档编号:24196657 上传时间:2023-05-25 格式:DOCX 页数:22 大小:1.47MB
下载 相关 举报
可振动感应切换的电子音乐.docx_第1页
第1页 / 共22页
可振动感应切换的电子音乐.docx_第2页
第2页 / 共22页
可振动感应切换的电子音乐.docx_第3页
第3页 / 共22页
可振动感应切换的电子音乐.docx_第4页
第4页 / 共22页
可振动感应切换的电子音乐.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

可振动感应切换的电子音乐.docx

《可振动感应切换的电子音乐.docx》由会员分享,可在线阅读,更多相关《可振动感应切换的电子音乐.docx(22页珍藏版)》请在冰豆网上搜索。

可振动感应切换的电子音乐.docx

可振动感应切换的电子音乐

可振动感应的电子音乐

一、设计目的

1、通过无源蜂鸣器与振动传感器外接模块实现电子音乐的切换功能。

2、学习相关器件的知识,更深入的了解单片机的构成及作用,并能运用单片机处理生活中的问题。

二、硬件原理

1、振动传感器

三、软件原理

1、按键消抖原理:

当按键被按下的时候,电路导通接地,I/O口为低电平;当按键未被下时,电路断开,I/O口保持高电平的。

但一般的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。

因而在闭合及断开的瞬间均伴随有一连串的抖动,假如不加以处理,会导致按键被识别为按下多次。

为了不产生这种现象而作的措施就是按键消抖。

方法1:

使用延时

如果按键较多,常用软件方法去抖,即检测出键闭合后执行一个延时程序,5ms~10ms的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。

当检测到按键释放后,也要给5ms~10ms的延时,待后沿抖动消失后才能转入该键的处理程序。

2、定时器中断原理:

中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。

当中央处理机正在处理某事件时外界发生紧急请求,CPU将暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的工程则为中断。

定时器0和1的中断请求标志位是TF0和TF1,当定时器寄存器出现溢出时,溢出标志位会被置位,如果定时器0/1的中断被打开,则定时器中断发生,当单片机去处理该中断时,定时器的溢出标志位会被硬件清除。

3、振动感应播放原理:

振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

每一个音符的发声频率是不同的,我们需要用计时器来精确计时,用以产生方波,这样才能发出不用的音符声音。

C调各音符频率与计数值如图1所示,以下的简谱码是在晶振为12MHz的情况下计算的,换算为16进制的简谱码如程序中quzi[]数组所示。

图1C调各音符频率与计数值

本程序中,数组music[]即是要播放的音乐,格式为音符,节拍,音符,节拍,如此循环下去。

音符为要发出的音调,而节拍则是声音的持续时间。

如图,在数组music[]中,音符表示的格式为:

十位代表是低八度,中八度还是高八度,1代表高八度,2代表中八度,3代表高八度,个位代表简谱的音符,例如,0x15代表低八度的S0,如图即是低5S0,0x21代表中八度的DO,如图即是中1D0。

音符中,0x00代表结束符,表示整首歌曲演唱完毕,而0xff代表休止符,表示要休止100ms。

遇到这两种情况,都应该重新执行循环中的第一步。

其余情况则是正常播放。

在定时器中断中进行振动/倒置传感器的检测,因为每播放完一个音节(产生一个方波),都重新启动了定时器。

相当于在每个音节播放完就检测1次振动/倒置传感器的状态。

程序烧入单片机后,会自动进行演奏。

相比基础篇,在去除了按键控制后,在其中添加了振动切歌的新功能。

4、芯片振动传感器相关引脚:

图4芯片振动传感器相关引脚

四、软件流程与相关代码

1、软件流程

a.创建工程文件

b.编写代码

c.编译运行

d.创建Hex文件

e.下载编程

2、相关代码

/**********************

文件名称:

v_music.c

作者:

机智的璐璐璐璐

说明:

进行音乐播放的例程,按下key1键后开始播放音乐

修改记录:

***********************/

/**********************

基于STC15F2K60S2系列单片机C语言编程实现

使用如下头文件,不用另外再包含"REG51.H"

***********************/

#include

#defineuintunsignedint

#defineucharunsignedchar

sbitKey1=P3^2;//Key1对应触发外部中断0

sbitbeep=P3^4;//蜂鸣器

sbitvibrate=P2^4;//振动传感器

uchartimeh,timel,jindu=0,gequ=0,zanting=0;//定义定时器的重装值

bitflag;//播放标志位

ucharcodemusic1[]={

//音乐代码,歌曲为《生日快乐》,格式为:

音符,节拍,音符,节拍,

//音符的十位代表是低八度,中八度还是高八度,1代表高八度,2代表中八度,3代表高八度

//个位代表简谱的音符,例如0x15代表低八度的S0,0x21代表中八度的DO。

//节拍则是代表音长,例如:

0x10代表一拍,0x20代表两拍,0x05代表1/2拍

0x15,0x05,0x15,0x05,

0x16,0x10,0x15,0x10,

0x31,0x10,0x17,0x20,

0x15,0x05,0x15,0x05,

0x16,0x10,0x15,0x10,

0x32,0x10,0x31,0x20,

0x15,0x05,0x15,0x05,

0x35,0x10,0x33,0x10,

0x31,0x10,0x17,0x10,

0x16,0x10,0x34,0x05,

0x34,0x05,0x33,0x10,

0x31,0x10,0x32,0x10,

0x31,0x10,0x00,0x00

};

ucharcodemusic2[]={//歌曲为小毛驴

0x21,0x05,0x21,0x05,

0x21,0x05,0x23,0x05,

0x25,0x05,0x25,0x05,

0x25,0x05,0x25,0x05,

0x26,0x05,0x26,0x05,

0x26,0x05,0x31,0x05,

0x25,0x20,0x24,0x05,

0x24,0x05,0x24,0x05,

0x26,0x05,0x23,0x05,

0x23,0x05,0x23,0x05,

0x23,0x05,0x22,0x05,

0x22,0x05,0x22,0x05,

0x22,0x05,0x25,0x15,

0x25,0x05,0x21,0x05,

0x21,0x05,0x21,0x05,

0x23,0x05,0x25,0x05,

0x25,0x05,0x25,0x05,

0x25,0x05,0x26,0x05,

0x26,0x05,0x26,0x05,

0x31,0x05,0x25,0x20,

0x24,0x05,0x24,0x05,

0x24,0x05,0x26,0x05,

0x21,0x05,0x21,0x05,

0x21,0x05,0x23,0x05,

0x25,0x05,0x25,0x05,

0x25,0x05,0x25,0x05,

0x26,0x05,0x26,0x05,

0x26,0x05,0x31,0x05,

0x25,0x20,0x24,0x05,

0x24,0x05,0x24,0x05,

0x23,0x03,0x23,0x03,

0x23,0x03,0x23,0x03,

0x23,0x05,0x23,0x05,

0x22,0x05,0x22,0x05,

0x22,0x05,0x23,0x05,

0x21,0x20,0x00,0x00

};

ucharcodemusic3[]={//歌曲为天空之城

0x16,0x05,0x17,0x05,

0x21,0x15,0x17,0x05,

0x21,0x10,0x23,0x10,

0x17,0x30,0x23,0x10,

0x16,0x15,0x15,0x05,

0x16,0x10,0x21,0x10,

0x15,0x30,0x13,0x10,

0x14,0x15,0x13,0x05,

0x14,0x05,0x21,0x05,

0x21,0x10,0x13,0x30,

0x21,0x10,0x17,0x10,

0x14,0x05,0x14,0x10,

0x17,0x10,0x17,0x20,

0xff,

0x16,0x05,0x17,0x05,

0x21,0x15,0x17,0x05,

0x21,0x10,0x23,0x10,

0x17,0x30,0x13,0x05,

0x13,0x05,0x16,0x15,

0x15,0x05,0x16,0x10,

0x21,0x10,0x15,0x30,

0x13,0x10,0x14,0x10,

0x21,0x05,0x17,0x05,

0x17,0x10,0x21,0x10,

0x22,0x10,0x23,0x05,

0x21,0x20,0xff,

0x21,0x05,0x17,0x05,

0x16,0x10,0x17,0x10,

0x15,0x10,0x16,0x20,

0xff,

0x21,0x05,0x22,0x05,

0x23,0x15,0x22,0x10,

0x23,0x10,0x24,0x10,

0x25,0x05,0x22,0x30,

0x15,0x10,0x22,0x03,

0x21,0x03,0x17,0x03,

0x21,0x03,0x21,0x10,

0x21,0x05,0x22,0x10,

0x23,0x05,0x23,0x40,

0x16,0x05,0x17,0x05,

0x21,0x10,0x17,0x05,

0x21,0x05,0x22,0x10,

0x21,0x15,0x15,0x05,

0x15,0x20,0x24,0x10,

0x23,0x10,0x22,0x10,

0x21,0x10,0x23,0x30,

0x16,0x05,0x17,0x05,

0x21,0x15,0x17,0x05,

0x21,0x10,0x23,0x10,

0x17,0x30,0x13,0x10,

0x16,0x15,0x15,0x05,

0x16,0x10,0x21,0x10,

0x15,0x30,0x13,0x10,

0x14,0x10,0x21,0x05,

0x17,0x05,0x17,0x10,

0x21,0x10,0x22,0x10,

0x23,0x05,0x21,0x05,

0x21,0x20,0x21,0x05,

0x17,0x05,0x16,0x10,

0x17,0x10,0x15,0x10,

0x16,0x40,0x00,0x00

};

ucharcodequzi[]={//此数组数据为各个音符在定时器中的重装值,第一列是高位,第二列是低位

0xf8,0x8c,//低八度,低1

0xf9,0x5b,

0xfa,0x15,//低3

0xfa,0x67,

0xfb,0x04,//低5

0xfb,0x90,

0xfc,0x0c,//低7

0xfc,0x44,//中央C调

0xfc,0xac,//中2

0xfd,0x09,

0xfd,0x34,//中4

0xfd,0x82,

0xfd,0xc8,//中6

0xfe,0x06,

0xfe,0x22,//高八度,高1

0xfe,0x56,

0xfe,0x6e,//高3

0xfe,0x9a,

0xfe,0xc1,//高5

0xfe,0xe4,

0xff,0x03//高7

};

/**********************

函数名称:

voiddelay(unsignedintxms)

功能描述:

延时

入口参数:

xms:

输入需要延时的毫秒值

出口参数:

备注:

***********************/

voiddelay(unsignedintxms)

{

uinti,j;

for(i=xms;i>0;i--)

for(j=124;j>0;j--);

}

/**********************

函数名称:

ucharquyin(uchartem)

功能描述:

在quzi数组中,找到music数组定义的简谱音符的重装值,并返回其在quzi数组中的位置

入口参数:

tem:

music数组中定义的简谱音符

出口参数:

返回的是tem音符在quzi数组中的位置值

备注:

***********************/

ucharquyin(uchartem)

{

ucharqudiao,jp,weizhi;//定义曲调,音符和位置

qudiao=tem/16;//高4位是曲调值

jp=tem%16;//低4位是音符

if(qudiao==1)//当曲调值为1时,即是低八度,低八度在quzi数组中基址为0

qudiao=0;

elseif(qudiao==2)//当曲调值为2时,即是中八度,中八度在quzi数组中基址为14

qudiao=14;

elseif(qudiao==3)//当曲调值为3时,即是高八度,高八度在quzi数组中,基址为28

qudiao=28;

weizhi=qudiao+(jp-1)*2;//通过基址加上音符作为偏移量,即可定位此音符在quzi数组中的位置

returnweizhi;//返回这一个位置值

}

/**********************

函数名称:

voidplaymusic()

功能描述:

播放音乐

入口参数:

出口参数:

备注:

***********************/

voidplaymusic()

{

ucharp,m,tem;//m为节拍

while

(1)

{while(zanting)

beep=0;

if(gequ==0)//歌曲选择位为0,则播放第一首歌

{

p=music1[jindu];//如果碰到结束符,延时1秒,回到开始再来一遍

if(p==0x00)

{

jindu=0;

delay(1000);

break;

}

elseif(p==0xff)//若碰到休止符,延时100ms,继续取下一音符

{

jindu=jindu+1;

delay(100);

TR0=0;

break;

}

else//正常情况下取音符和节拍

{

tem=quyin(music1[jindu]);//取出当前音符在quzi数组中的位置值

timeh=quzi[tem];//把音符相应的计时器重装载值赋予timeh和timel

timel=quzi[tem+1];

jindu++;

TH0=timeh;//把timeh和timel赋予计时器

TL0=timel;

m=music1[jindu];//取得节拍

jindu++;

}

TR0=1;//开定时器1

delay(m*180);//等待节拍完成,通过P3^4口输出音频

TR0=0;//关定时器1

}

elseif(gequ==1)//歌曲选择位为1,则播放第二首歌

{

p=music2[jindu];//如果碰到结束符,延时1秒,回到开始再来一遍

if(p==0x00)

{

jindu=0;

delay(1000);

break;

}

elseif(p==0xff)//若碰到休止符,延时100ms,继续取下一音符

{

jindu=jindu+1;

delay(100);

TR0=0;

break;

}

else//正常情况下取音符和节拍

{

tem=quyin(music2[jindu]);//取出当前音符在quzi数组中的位置值

timeh=quzi[tem];//把音符相应的计时器重装载值赋予timeh和timel

timel=quzi[tem+1];

jindu++;

TH0=timeh;//把timeh和timel赋予计时器

TL0=timel;

m=music2[jindu];//取得节拍

jindu++;

}

TR0=1;//开定时器1

delay(m*300);//等待节拍完成,通过P3^4口输出音频

TR0=0;//关定时器1

}

elseif(gequ==2)//歌曲选择位为2,则播放第三首歌

{

p=music3[jindu];//如果碰到结束符,延时1秒,回到开始再来一遍

if(p==0x00)

{

jindu=0;

delay(1000);

break;

}

elseif(p==0xff)//若碰到休止符,延时100ms,继续取下一音符

{

jindu=jindu+1;

delay(100);

TR0=0;

break;

}

else//正常情况下取音符和节拍

{

tem=quyin(music3[jindu]);//取出当前音符在quzi数组中的位置值

timeh=quzi[tem];//把音符相应的计时器重装载值赋予timeh和timel

timel=quzi[tem+1];

jindu++;

TH0=timeh;//把timeh和timel赋予计时器

TL0=timel;

m=music3[jindu];//取得节拍

jindu++;

}

TR0=1;//开定时器1

delay(m*200);//等待节拍完成,通过P3^4口输出音频

TR0=0;//关定时器1

}

}

}

/**********************

函数名称:

voidinit_sys()

功能描述:

系统初始化,功能是配置IO口

入口参数:

出口参数:

备注:

 

***********************/

voidinit_sys()

{

P0M0=0xff;

P0M1=0x00;

P2M0=0x08;

P2M1=0x00;

P3M0=0x10;

P3M1=0x00;

P4M0=0x00;

P4M1=0x00;

P5M0=0x00;

P5M1=0x00;

}

/**********************

函数名称:

voidinit()

功能描述:

定时器和外部中断的初始化

入口参数:

出口参数:

备注:

***********************/

voidinit()

{

TMOD=0x01;

TH0=0xD8;

TL0=0xEF;

IE=0x87;

//IP=0x02;

IP=0x01;

TR0=0;

}

/**********************

函数名称:

Exint0

功能描述:

Key1对应的外部中断0的中断响应函数

***********************/

voidExint0()interrupt0

{

if(Key1==0)

{delay(10);//延时消抖

if(Key1==0)

zanting=~zanting;//zanting==1暂停播放

}

}

voidmain()

{

init_sys();

init();

P0=0x00;

vibrate=1;

flag=0;//播放标志位清零

while

(1)

{

playmusic();

}

}

/**********************

函数名称:

voidtim1()interrupt1

功能描述:

定时器0中断处理,重新装值,并把beep值取反,产生方波

入口参数:

出口参数:

备注:

***********************/

voidtim1()interrupt1//计时器控制频率

{

TH0=timeh;

TL0=timel;

if(zanting==1)

beep=0;

else

{

beep=~beep;

if(vibrate==0)

{

jindu=0;//歌曲的进度清零,从头开始演唱

gequ++;

if(gequ==3)

gequ=0;

}

}

}

五、设计结果

单片机上电后,初始现象为自动播放第一首歌,敲击板子使其振动,切换播放第二首歌,同理再次振动播放第三首歌,再次振动重新从头播放,按K1键停止播放。

六、操作说明

K1键用于暂停和播放歌曲,敲击板子用于切换歌曲。

七、心得体会

本来这个可振动感应的电子音乐是没有代码的,但是结合之前提供的消抖技术,还有延时技术,以及本来提供的振动感应的代码,就可以做出这个程序。

但是由于之前的可切换电子音乐也没有代码,所以在实现的过程中有在网上搜素过相关资料,才最终实现了功能。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 环境科学食品科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1