基于单片机的电子琴设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

郑州航空工业管理学院
单片机课程设计说明书 14 届电子信息工程专业 82 班级
题目
学号
姓名
指导教师
二О一六年十二月二十三日
目录
摘要 (3)
一、电子琴的基本原理 (4)
1.设计的内容
2.整体的工作原理
3.发音原理
二、电子时钟的硬件设计 (5)
1.硬件原理图
2.键盘设计
3.时钟电路
4.复位电路
5.元件清单
6.数码管显示部分
7.发音部分设计
8.硬件调试
三、电子时钟的软件设计 (9)
1.键盘扫描程序
2.功能转移程序
3.琴键处理程序
4.自动播放歌曲程序
5.程序流程图
6.设计源程序
四、课程设计总结与指导教师评语 (18)
摘要
随着社会的发展进步,音乐逐渐成为我们生活中很重要的一部分,有人曾说喜欢音乐的人不会向恶。

我们都会抽空欣赏世界名曲,作为对精神的洗礼。

本论文设计一个基于单片机的简易电子琴。

我们对于电子琴如何实现其功能,如音色选择、声音强弱控制、节拍器、自动放音功能等等也很好奇。

电子琴是现代电子科技与音乐结合的产物,是一种新型的键盘乐器。

它在现代音乐扮演着重要的角色,单片机具有强大的控制功能和灵活的编程实现特性,它已经溶入现代人们的生活中,成为不可替代的一部分。

本文的主要内容是用AT89S51单片机为核心控制元件,设计一个电子琴。

以单片机作为主控核心,与键盘、扬声器等模块组成核心主控制模块,在主控模块上设有16个按键和扬声器。

本系统运行稳定,其优点是硬件电路简单,软件功能完善,控制系统可靠,性价比较高等,具有一定的实用和参考价值。

关键词:AT89S51单片机音色节拍器自动放音
一、电子琴的基本原理
1、本次设计的内容是:
利用所给键盘的16,15,14,13,12,11,10,9七个键,能够发出7个不同的音调,而且8,7,6按键可以自动播放歌曲,要求按键按下时发声,当系统扫描到键盘按下,则快速检测出是哪一个按键被按下,然后单片机的定时器启动,发出一定频率的脉冲,该频率的脉冲经喇叭驱动电路放大滤波后,就会发出相应的音调,p1.7控制着蜂鸣器发出声音,在此基础上我们组又增加了数码管显示部分,当发出1,2,3,4,5,6,7音调时通过p2口控制数码管是分别显示1,2,3,4,5,6,7当播放音乐时数码管分别显示1,2,3 。

2、整体工作原理:
采用AT89C52单片机作为主控芯片,设置键盘、蜂鸣器等外围器件,另外还用到一些简单器件如:两位数码管,和NPN型三极管及电阻等。

利用按键实现音符和音调的输入;两位的数码管进行被操作的按键显示;用NPN型三极管8550实现低音频功率放大;最后用蜂鸣器发音。

AT89C52单片机是大规模集成电路技术发展的产物,具有高性能、高速度、体积小、价格低廉、稳定可靠、应用广泛的特点。

同时具有强大的控制功能和灵活的编程实现特性,由于本设计主要用于人们娱乐方面,因此在设计上尽量使其安全以及简单易操作。

具有经济可行性、技术可行性、实物应用性。

3、发音原理:
若要产生音频脉冲,只要算出某一音频的周期(频率),再将此周期除以2,即为半周期的时间。

利用定时器计时半周期时间,每当计时终止后就将P1.7反相,然后重复计时再反相。

就可在P1.7引脚上得到此频率的脉冲。

利用STC89C52的内部定时器使其工作计数器模式(MODE1)下,改变计数值TH0及TL0以产生不同频率的方法产生不同音阶。

计算举例,频率为523Hz,其周期T=1/523=1912μs,因此只要令计数器计时956μs/1μs=956,每计数956次时将I/O反相,就可得到中音DO(523Hz)。

计数脉冲值与频率的关系式是:N=fi÷2÷fr,式中,N是计数值;fi是机器频率(晶体振荡器为12MHz时,其频率为1MHz);fr是想要产生的频率。

其计数初值T的求法如下:T=65536-N=65536-fi÷2÷fr
例如:设K=65536,fi=1MHz,求中音DO(261Hz)。

T=65536-N=65536-fi÷2÷fr=65536-1000000÷2÷fr=65536-500000/fr,中音DO的T=65536-500000/523=64580
STC89C52单片机为12MHZ晶振,中音符与计数T0相关的计数值如表所示:
用单片机播放音乐,或者弹奏电子琴,实际上是按照特定的频率,输出一连串的方波。

为了输出合适的方波,首先应该知道音符与频率的关系。

二、电子时钟的硬件设计
1、硬件原理图:
本系统有主控芯片STC89C52、发音单元、显示模块、按键模块组成。

硬件电路要以单片机作为主控芯片,实现按键输入音符和音调,四位数码管的显示以及低音频功率放大和蜂鸣器发音。

2、键盘设计
单片机系统中,若按键较多时,通常采用矩阵式(也称行列式)键盘。

矩阵式键盘由行线和列线组成,按键位于行、列线的交叉点上。

显然,在按键数量较多时,矩阵式键盘较之独立式按键键盘要节省很多I/O口。

矩阵式键盘中,行、列线分别连接到按键开关的两端,行线通过上拉电阻接到+5V上.当无键按下时,行线处于高电平状态;当有键按下时,行、列线将导通,此时,行线电平将由与此行线相连的列线电平决定。

这是识别按键是否按下的关键。

图-矩阵键盘
3、时钟电路
单片机内部具有一个高增益反相放大器,用于构成振荡器。

通常在引脚Xl和X2跨接石英晶体和两个补偿电容构成自激振荡器,选择12MHz频率的石英晶体,补偿电容通常选择20pF左右的瓷片电容。

4、复位电路
单片机小系统常采用上电自动复位和手动按键复位两种方式实现系统的复位操作。

上电复位要求接通电源后,自动实现复位操作。

手动复位要求在电源接通的条件下,在单片机运行期间,用按钮开关操作使单片机复位。

上电自动复位通过电容C3充电来实现。

手动按键复位是通过按键将电阻R1与VCC接通来实现。

5、元件清单
6、数码管显示部分
当发出1,2,3,4,5,6,7音调时通过p2口控制数码管是分别显示1,2,3,4,5,6,7当播放音乐时数码管分别显示1,2,3 。

7、发音部分设计
如下图所示,发音电路是由蜂鸣器、三极管、上拉电阻构成。

由三极管来驱动扬声器发音的,同时加上拉电阻增强驱动电流,提高驱动能力。

图4发音电路
8、硬件调试
硬件调试主要是针对单片机部分进行的调试。

在上电之前,先确保电路中不存在断路或短路情况,这一工作是整个调试工作的第一步,也是非常重要的一个步骤。

在这部分调试中主要使用的工具是万用表,用来完成检测电路中是否存在断路或者短路情况的任务。

注意焊点之间,确保焊点没有短接在一起,同时注意焊点的美观,确保没有开路以及短路的现象出现。

在确保硬件电路正常且无异常情况(断路或短路)的情况下方可上电调试,上电调试的目的是检验电路是否接错,同时还要检验原理是否正确,在本次设计中,上电调试主要是检测单片机控制部分、数码管点亮部分、和音频转换电路硬件调试,
三、电子时钟的软件设计
1、键盘扫描程序:
检测是否有按键按下,有按键按下则记录按下键的键值,并跳转至功能转移程序;无按键按下,则返回键盘扫描程序继续检测。

2、功能转移程序:
对检测到的按键值进行判断,是琴键则跳转至琴键处理程序,是功能键则跳转至相应的功能程序,我们设计的功能程序有两种,即音色调节功能和自动播放乐曲的功能。

3、琴键处理程序:
根据检测到的按键值,查询音调表,给计时器赋值,使发出相应频率的声音。

4、自动播放歌曲程序:
检测到按键按下的是自动播放歌曲功能键后执行该程序,电子琴会自动播放事先已经存放的歌曲,歌曲播放完毕之后自动返回至键盘扫描程序,继续等待是否有按键按下。

5、程序流程图
图5 流程图
6、设计源程序:
/*说明************************************************************************* 曲谱存贮格式unsigned char code MusicName{音高,音长,音高,音长...., 0,0}; 末尾:0,0 表示结束(Important)
音高由三位数字组成:个位是表示1~7 这七个音符;十位是表示音符所在的音区:1-低音,2-中音,3-高音;百位表示这个音符是否要升半音: 0-不升,1-升半音。

音长最多由三位数字组成:个位表示音符的时值,其对应关系是:
|数值(n): |0 |1 |2 |3 | 4 | 5 | 6
|几分音符: |1 |2 |4 |8 |16 |32 |64 音符=2^n
十位表示音符的演奏效果(0-2): 0-普通,1-连音,2-顿音
百位是符点位: 0-无符点,1-有符点
调用演奏子程序的格式
Play(乐曲名,调号,升降八度,演奏速度);
|乐曲名: 要播放的乐曲指针,结尾以(0,0)结束;
|调号(0-11) : 是指乐曲升多少个半音演奏;
|升降八度(1-3) : 1:降八度, 2:不升不降, 3:升八度;
|演奏速度(1-12000): 值越大速度越快;
#define __SOUNDPLAY_H_REVISION_FIRST__
#include <reg52.h>
//**************************************************************************
#define SYSTEM_OSC 12000000 //定义晶振频率12000000HZ
#define SOUND_SPACE 4/5 //定义普通音符演奏的长度分率,//每4分音符间隔
#define uchar unsigned char
sbit P2_0 = P2^0;
sbit P2_1 = P2^1;
sbit P2_2 = P2^2;
sbit P2_3 = P2^3;
sbit P2_4 = P2^4;
sbit P2_5 = P2^5;
sbit P2_6 = P2^6;
sbit P2_7 = P2^7;
sbit BeepIO = P1^7; //定义输出管脚
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90};
unsigned int code FreTab[12] = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表unsigned char code SignTab[7] = { 0,2,4,5,7,9,11 }; //1~7在频率表中的位置
unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };
unsigned char Sound_Temp_TH0,Sound_Temp_TL0; //音符定时器初值暂存
unsigned char Sound_Temp_TH1,Sound_Temp_TL1; //音长定时器初值暂存
//**************************************************************************
void delay(uchar i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
void InitialSound(void)
{
BeepIO = 1;
Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; // 计算TL1应装入的初值(10ms的初装值)
Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256; // 计算TH1应装入的初值
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TMOD |= 0x11;
ET0 = 1;
ET1 = 0;
TR0 = 0;
TR1 = 0;
EA = 1;
}
void BeepTimer0(void) interrupt 1 //音符发生中断
{
BeepIO = !BeepIO;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0;
}
//************************************************************************** void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed) {
unsigned int NewFreTab[12]; //新的频率表
unsigned char i,j;
unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
for(i=0;i<12;i++) // 根据调号及升降八度来生成新的频率表
{
j = i + Signature;
if(j > 11)
{
j = j-12;
NewFreTab[i] = FreTab[j]*2;
}
else
NewFreTab[i] = FreTab[j];
if(Octachord == 1)
NewFreTab[i]>>=2;
else if(Octachord == 3)
NewFreTab[i]<<=2;
}
SoundLength = 0;
while(Sound[SoundLength] != 0x00) //计算歌曲长度
{
SoundLength+=2;
}
Point = 0;
Tone = Sound[Point];
Length = Sound[Point+1]; // 读出第一个音符和它时时值
LDiv0 = 12000/Speed; // 算出1分音符的长度(几个10ms)
LDiv4 = LDiv0/4; // 算出4分音符的长度
LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最长间隔标准
TR0 = 0;
TR1 = 1;
while(Point < SoundLength)
{
SL=Tone%10; //计算出音符
SM=Tone/10%10; //计算出高低音
SH=Tone/100; //计算出是否升半
CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出对应音符的频率
if(SL!=0)
{
if (SM==1) CurrentFre >>= 2; //低音
if (SM==3) CurrentFre <<= 2; //高音
Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值
Sound_Temp_TH0 = Temp_T/256;
Sound_Temp_TL0 = Temp_T%256;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿
}
SLen=LengthTab[Length%10]; //算出是几分音符
XG=Length/10%10; //算出音符类型(0普通1连音2顿音)
FD=Length/100;
LDiv=LDiv0/SLen; //算出连音音符演奏的长度(多少个10ms)
if (FD==1)
LDiv=LDiv+LDiv/2;
if(XG!=1)
if(XG==0) //算出普通音符的演奏长度
if (SLen<=4)
LDiv1=LDiv-LDiv4;
else
LDiv1=LDiv*SOUND_SPACE;
else
LDiv1=LDiv/2; //算出顿音的演奏长度
else
LDiv1=LDiv;
if(SL==0) LDiv1=0;
LDiv2=LDiv-LDiv1; //算出不发音的长度
if (SL!=0)
{
TR0=1;
for(i=LDiv1;i>0;i--) //发规定长度的音
{
while(TF1==0);
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TF1=0;
}
}
if(LDiv2!=0)
{
TR0=0; BeepIO=1;
for(i=LDiv2;i>0;i--) //音符间的间隔
{
while(TF1==0);
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TF1=0;
}
}
Point+=2;
Tone=Sound[Point];
Length=Sound[Point+1];
}
BeepIO = 1;
}
//**************************************************************************
#endif
#include <REG52.H>
#include "SoundPlay.h"
//*****************************Music**************************************** unsigned char code sound1[]={ 0x15,0x02, 0x00,0x00 };//1
unsigned char code sound2[]={ 0x16,0x02, 0x00,0x00 };//2
unsigned char code sound3[]={ 0x17,0x02, 0x00,0x00 };//3
unsigned char code sound4[]={ 0x18,0x02, 0x00,0x00 };//4
unsigned char code sound5[]={ 0x19,0x02, 0x00,0x00 };//5
unsigned char code sound6[]={ 0x1A,0x02, 0x00,0x00 };//6
unsigned char code sound7[]={ 0x1B,0x02, 0x00,0x00 };//7
unsigned char key;
//小毛驴
unsigned char code Music_Xiao[]={0x15,0x03, 0x15,0x03, 0x15,0x03, 0x17,0x03,
0x19,0x03, 0x19,0x03, 0x19,0x03, 0x19,0x03,
0x1A,0x03, 0x1A,0x03, 0x1A,0x03, 0x1F,0x03,0x19,0x02,
0x18,0x03, 0x18,0x03, 0x1A,0x03, 0x1A,0x03,
0x17,0x03, 0x17,0x03, 0x17,0x03, 0x17,0x03,
0x16,0x03, 0x16,0x03, 0x16,0x03, 0x16,0x03,0x6A,0x02, 0x19,0x02,
0x15,0x03, 0x15,0x03, 0x15,0x03, 0x17,0x03,
0x19,0x03, 0x19,0x03, 0x19,0x03, 0x19,0x03,
0x1A,0x03, 0x1A,0x03, 0x1A,0x03, 0x1F,0x03,0x19,0x02, 0x19,0x02,
0x18,0x03, 0x18,0x03, 0x1A,0x03, 0x1A,0x03,
0x17,0x03, 0x17,0x03, 0x17,0x03, 0x17,0x03,
0x16,0x03, 0x16,0x03, 0x16,0x03, 0x16,0x03,0x15,0x02,0x00,0x00,0x00,
};
//找朋友
unsigned char code Music_Zhao[]={0x19,0x03, 0x1A,0x03, 0x19,0x03, 0x1A,0x03, 0x19,0x03, 0x1A,0x03,
0x19,0x02, 0x19,0x03, 0x1F,0x03,0x1B,0x03,0x1A,0x03,0x19,0x02, 0x17,0x02,
0x19,0x03, 0x19,0x03, 0x17,0x03, 0x18,0x03, 0x19,0x03, 0x19,0x03, 0x17,0x02,
0x19,0x03, 0x19,0x03, 0x17,0x03, 0x18,0x03, 0x19,0x03, 0x19,0x03, 0x17,0x02,
0x15,0x03, 0x18,0x03, 0x17,0x03, 0x16,0x03,0x15,0x03,0x16,0x03,0x15,0x02,0x00, 0x00,0x00};
//两只老虎
unsigned char code Music_Two[] ={0x15,0x02, 0x16,0x02, 0x17,0x02, 0x15,0x02,
0x15,0x02, 0x16,0x02, 0x17,0x02, 0x15,0x02,
0x17,0x02, 0x18,0x02, 0x19,0x02,
0x17,0x02, 0x18,0x02, 0x19,0x02,
0x19,0x03, 0x1A,0x03, 0x19,0x02, 0x18,0x03, 0x17,0x02, 0x15,0x02,
0x15,0x02, 0x16,0x02, 0x17,0x02, 0x15,0x02,
0x15,0x02, 0x16,0x02, 0x17,0x02, 0x15,0x02,
0x17,0x02, 0x18,0x02, 0x19,0x02,
0x17,0x02, 0x18,0x02, 0x19,0x02,
0x19,0x03, 0x1A,0x03, 0x19,0x02, 0x18,0x03, 0x17,0x02, 0x15,0x02,
0x17,0x02, 0x0f,0x02, 0x15,0x02,
0x17,0x02, 0x0f,0x02, 0x15,0x02,
0x17,0x02, 0x0f,0x02, 0x15,0x02,
0x19,0x03, 0x1A,0x03, 0x19,0x02, 0x18,0x03, 0x17,0x02, 0x15,0x02,
0x19,0x03, 0x1A,0x03, 0x19,0x02, 0x18,0x03, 0x17,0x02, 0x15,0x02,
0x17,0x02, 0x0f,0x02, 0x15,0x02,
0x17,0x02, 0x0f,0x02, 0x15,0x02,0x00, 0x00,};
//***********************************************************************************
void delayms(unsigned int z)
{
unsigned int x,y;
for (x = z; x>0; x--)
for(y=110; y>0; y-- );
}
void keyscan()//矩阵键盘扫描函数
{
unsigned char x,y;
P3=0xf0;
if (P3!=0xf0)
{
delayms(10);
if (P3!=0xf0)
{
x=P3&0xf0;
P3=0x8f;
y=P3&0x8f;
key=x|y;
while(P3!=0x8f);
switch (key)
{
case 0xe7: key=16;
{
P0=table[1];P2_7 = 0;delay(5);P2_7 = 1;
P0=table[1];P2_6 = 0;delay(5);P2_6 = 1; }
Play(sound1,0,3,360);
break;
case 0xeb: key=15;
{
P0=table[2];P2_6 = 0;delay(5);P2_6 = 1;
P0=table[2];P2_5 = 0;delay(5);P2_5 = 1; }
Play(sound2,0,3,360);
break;
case 0xed: key=14;
{
P0=table[3];P2_5 = 0;delay(5);P2_5= 1;
P0=table[3];P2_4 = 0;delay(5);P2_4= 1; }
Play(sound3,0,3,360);
break;
case 0xee: key=13;
{
P0=table[4];P2_4 = 0;delay(5);P2_4 = 1;
P0=table[4];P2_3 = 0;delay(5);P2_3 = 1; }
Play(sound4,0,3,360);
break;
case 0xd7: key=12;
{
P0=table[5];P2_3 = 0;delay(5);P2_3 = 1;
P0=table[5];P2_2 = 0;delay(5);P2_2 = 1; }
Play(sound5,0,3,360);
break;
case 0xdb: key=11;
{
P0=table[6];P2_2 = 0;delay(5);P2_2 = 1;
P0=table[6];P2_1 = 0;delay(5);P2_1 = 1; }
Play(sound6,0,3,360);
break;
case 0xdd: key=10;
{
P0=table[7];P2_1 = 0;delay(5);P2_1 = 1;
P0=table[7];P2_0 = 0;delay(5);P2_0 = 1; }
Play(sound7,0,3,360);
break;
case 0xb7: key=8;
{
P0=table[1];P2_7 = 0;delay(5);P2_7 = 0;
P0=table[1];P2_6 = 0;delay(5);P2_6 = 0;
P0=table[1];P2_5 = 0;delay(5);P2_5 = 0;
P0=table[1];P2_4 = 0;delay(5);P2_4 = 0;
P0=table[1];P2_3 = 0;delay(5);P2_3= 0;
P0=table[1];P2_2 = 0;delay(5);P2_2 = 0;
P0=table[1];P2_1 = 0;delay(5);P2_1 = 0;
P0=table[1];P2_0 = 0;delay(5);P2_0 = 0;
}
Play(Music_Two,0,3,360);
break;
case 0xbb: key=7;
{
P0=table[2];P2_7 = 0;delay(5);P2_7 = 0;
P0=table[2];P2_6 = 0;delay(5);P2_6 = 0;
P0=table[2];P2_5 = 0;delay(5);P2_5 = 0;
P0=table[2];P2_4 = 0;delay(5);P2_4 = 0;
P0=table[2];P2_3 = 0;delay(5);P2_3 = 0;
P0=table[2];P2_2 = 0;delay(5);P2_2 = 0;
P0=table[2];P2_1 = 0;delay(5);P2_1 = 0;
P0=table[2];P2_0 = 0;delay(5);P2_0 = 0;
}
Play(Music_Xiao,0,3,360);
break;
case 0xbd: key=6;
{
P0=table[3];P2_7 = 0;delay(5);P2_7 = 0;
P0=table[3];P2_6 = 0;delay(5);P2_6 = 0;
P0=table[3];P2_5 = 0;delay(5);P2_5 = 0;
P0=table[3];P2_4 = 0;delay(5);P2_4 = 0;
P0=table[3];P2_3 = 0;delay(5);P2_3 = 0;
P0=table[3];P2_2 = 0;delay(5);P2_2 = 0;
P0=table[3];P2_1 = 0;delay(5);P2_1 = 0;
P0=table[3];P2_0 = 0;delay(5);P2_0 = 0;
}
Play(Music_Zhao,0,3,360);
break;
default: key=88;
break; }
}
}
}
main()
{
InitialSound();
while(1)
{
keyscan();
}
}
四、课程设计总结与指导教师评语
2.指导教师评语。

相关文档
最新文档