资源描述
单片机课程设计0915232037 袁毅
2011
学号:0915232037 姓名:袁毅
单片机课程设计
多功能电子琴
课程设计
多功能led可调音电子琴
一、前言:
我们生活在一个信息时代,各种电子产品层出不穷,作为一个通信工程专业的学生,了解这些电子产品的基本组成和设计原理是十分必要的。我们学习的是51单片机原理与应用,而课程设计正是对我们学习的理论的实践与巩固。本设计主要介绍的是基于51单片机的简易电子琴,设计的一个具有若干功能的简易电子琴,本设计使用的语言是C语言。
二、设计目的:
(1)能够对电子电路、电子元器件等方面的知识有进一步的认识,独立对其进行测试与检查;
(2)熟悉89S51单片机的内部结构和功能,合理使用其内部寄存器,能够完成编程设计工作;
(3)为实现预期功能,能够对系统进行快速的调试,并能够对功能故障进行分析,急时修改相关软硬件;
(4)对软件编程,排错调试,相关仪器设备的使用技能等方面得到较全面的锻炼和提高。
三、系统功能要求:
1.具有发出两种不同音调1234567和1八个音的功能。并且不同的音伴随着不同的led灯亮,依次为一个、两个等。
2. 设计完整的原理图电路,包括时钟电路、复位电路以及键盘接口电路等。
四、实验原理:
音乐产生原理及硬件设计由于一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0来产生这样方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系弄正确即可。本次设计中单片机晶振为12MHZ,那么定时器的计数周期为1MHZ,假如选择工作方式1,那T值便为T=65536-1000000/2/f相应的频率 ,那么根据不同的频率计算出应该赋给定时器的计数值:
音阶频率表 高八位 0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,
0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,
0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,
音阶频率表 低八位 0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,
0x8F,0xEE,0x44,0x6B,0xB4,0xF4,0x2D,
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,
系统整体安排如下:
1、按下K1键发出1的声音。
2、按下K2键发出2的声音。
3、按下K3键发出3的声音。
4、按下K4键发出4的声音。
5、按下K5键发出5的声音。
6、按下K6键发出6的声音。
7、按下K7键发出7的声音。
8、按下K8键发出1的声音。
9、单片机可采用AT89C51、AT89C52、AT89S52、fosc=12MHz。
10、时钟电路,复位电路的设计。
89s51单片机根据不同的琴键产生不同的乐曲音符,并经过信号放大,由喇叭放出。系统整体方案如图所示:
琴键 电路
放大
电路
P2.7
P1.0
|
P1.7
复位电路
单片机
时钟电路
P2.0
|
P2.2
音调选择电路
五:实验步骤:
1、硬件系统原理图如图:
2、频率、声音的实现和产生
单片机的频率和声音输出的原理是,利用琴键控制定时器的开中断和闭中断,即实现发音和闭音。在此期间再通过对定时器的定时时间进行控制来产生不同频率的方波,驱动嗡宁器发出不同音阶的声音。把相应琴键对应的音符变换为定常数,作为数据表格存放在存储器中。由程序查表得到定时常数,用以控制定时器产生方波的频率。当下一个琴键按下时,再查下此琴键所对应音符的定时常数。依次进行下去,就可以演奏出自己所要的歌曲。
3、键盘的方案选择
此系统琴键输入是通过独立式键盘来完成的。由于89s51单片机的八位I/O口足以能实现控制各音阶的输出,并且独立式键盘的编程容易易懂,结构简单,实现起来方便,而且每个按键单独占有一根I/O接口线,每个I/O口的工作状态互不影响,所以采用独立式键盘。P1.0~P1.7 口分别对应琴键1~7输入,如下图所示。
4、关于键盘的抖动问题的分析和解决
当用手按下一个键时,如图所示,往往按键在闭合位置和断开位置之间跳几下才稳定到闭合状态的情况;在释放一个键时,也回会出现类似的情况。这就是抖动。抖动的持续时间随键盘材料和操作员而异,不过通常总是不大于10ms。很容易想到,抖动问题不解决就会引起对闭合键的识别。
键按下
前沿抖动
后沿抖动
闭合
稳定
用软件方法可以很容易地解决抖动问题,这就是通过延迟10ms来等待抖动消失,这之后,再读入键盘码。
键抖动信号波形
延迟10ms的程序为:
void delay(uchar t)
{
uchar x;
unsigned long y;
for(x=0;x<t;x++)
{
for(y=0;y<5000;y++);
}
}
5.放大电路分析
此部分的放大电路简单容易实现。可以采用一个小功率PNP型硅管8550,利用“分压偏置式工作点稳定直流通路”,达到了对静态工作点的稳定。分压电阻分别选择1K和5.5K。蜂鸣器一端接+5V电压,一端接晶体管的发射极。由P2.7输出预定的方波,加到晶体管进行放大,再输出到嗡宁器,很好的实现了频率、声音的转换。
放大电路输出原理图
6.时钟电路和复位电路的论证和分析:
此系统的时钟电路设计是采用的内部方式,即利用芯片内部的振荡电路。
89s51内部有一个用于构成振荡器的高增益反相放大器。引脚XTAL1和XTAL2分别是此放大器的输入端和输出端。这个放大器与作为反馈元件的片外晶体谐振器一起构成一个自激振荡器。外接晶体谐振器以及电容CX1和CX2构成并联谐振电路,接在放大器的反馈回路中。对外接电容的值虽然没有严格的要求,但电容的大小会影响震荡器频率的高低、震荡器的稳定性、起振的快速性和温度的稳定性。因此,此系统电路的晶体振荡器的值为12 MHz,电容应尽可能的选择陶瓷电容,电容值约为22μF。
复位电路的论证和分析:
89s51的复位是由外部的复位电路来实现的。片内复位电路是复位引脚RST通过一个斯密特触发器与复位电路相连,斯密特触发器用来抑制噪声,它的输出在每个机器周期的S5P2,由复位电路采样一次。复位电路通常采用上电自动复位和按钮复位两种方式,此电路系统采用的是上电与按钮复位电路,如图所示。当时钟频率选用12MHz时,C取22μF,R2约为100Ω,R1约为10KΩ。
MSC-51片内振荡电路和复位电路原理图
六、系统软件设计
1、系统程序流程如图所示:
程序开始
关闭定时器,进行
下一次琴键识别
读P1口的状态
延迟10ms
Y
再读P1口的状态
判断是否是抖动
N
判断是几号琴键,
并跳转到相应的程序
查表得相应琴键的定时初值
重装定时器T0处值
对P2.7求反
中断返回
启动定时器T0
Y
等待中断,并判断此次琴键是否被释放
中断程序流程图
主程序流程图
2、程序清单:
#include<reg51.h>
#define uchar unsigned char
sbit key1=P1^0;//按键do
sbit key2=P1^1;//按键re
sbit key3=P1^2;//按键mi
sbit key4=P1^3;//按键fa
sbit key5=P1^4;//按键so
sbit key6=P1^5;//按键la
sbit key7=P1^6;//按键ti
sbit key8=P1^7;//按键do
sbit keyu=P2^0;//按键升高音阶
sbit keyd=P2^1;//按键降低音阶
sbit keym=P2^2;//按键示例音乐
sbit speaker=P2^7;//定义音乐输出端口
sbit a=P0^0;
sbit b=P0^1;
sbit c=P0^2;
sbit d=P0^3;
sbit e=P0^4;
sbit f=P0^5;
sbit g=P0^6;
sbit h=P0^7;
uchar timer0h,timer0l,time;
code uchar FREQH[]={
0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,
0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,
0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,
} ;// 音阶频率表 高八位
code uchar FREQL[]={
0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,
0x8F,0xEE,0x44,0x6B,0xB4,0xF4,0x2D,
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,
}; // 音阶频率表 低八位
code uchar song[]={
5,2,1, 1,3,1, 2,3,1, 3,3,1, 2,3,1, 3,3,1, 4,3,1,
5,3,1, 5,3,1, 5,3,1, 4,3,1, 3,3,1, 2,3,1, 2,3,3,
5,2,1, 1,3,1, 2,3,1, 3,3,1, 2,3,1, 3,3,1, 4,3,1,
5,3,1, 5,3,1, 5,3,1, 6,3,1, 5,3,2, 3,3,2, 1,3,2,
1,3,1, 6,2,1, 2,3,1, 2,3,1, 3,3,1, 3,3,1, 1,3,2,
5,3,1, 1,3,1, 5,2,1, 1,3,1, 7,2,1, 1,3,3, 1,3,1,
6,2,1, 2,3,1, 2,3,1, 3,3,1, 3,3,1, 4,3,1, 4,3,1,
4,3,1, 3,3,1, 2,3,1, 1,3,1, 1,3,2, 0,0,0
};//简单爱
void delay(uchar t)
{
uchar x;
unsigned long y;
for(x=0;x<t;x++)
{
for(y=0;y<5000;y++);
}
}
void int0()
{
TMOD=1;
TH0=timer0h;
TL0=timer0l;
EA=1;
ET0=1;
TR0=1;
delay(time);
}
void t0int() interrupt 1
{
TH0=timer0h;
TL0=timer0l;
speaker=!speaker;
}
void main()
{
uchar m,i;
int k;
k=1;
while(1)
{
if(!keym)
{
i=0;
while(i<192)
{
m=song[i]+7*song[i+1]-1;
timer0h=FREQH[m];
timer0l=FREQL[m];
time=song[i+2];
i=i+3;
int0();
TR0=0;
while (keym==0)
{
i=192;
}
}
}
if(!keyu)
{
k++;
if(k==4)
k=1;
}
if(!keyd)
{
k--;
if(k==0)
k=3;
}
if(!key1)
{ a=0;b=1;c=1;d=1;e=1; f=1; g=1; h=1;
timer0h=FREQH[7*k-7];
timer0l=FREQL[7*k-7];
int0();
while (key1==0);
TR0=0; delay(0.3); a=1;b=1;c=1;d=1;e=1; f=1; g=1; h=1;
}
if(!key2)
{ a=0;b=0;c=1;d=1;e=1; f=1; g=1; h=1;
timer0h=FREQH[7*k-6];
timer0l=FREQL[7*k-6];
int0();
while (key2==0);
TR0=0; delay(0.3); a=1;b=1;c=1;d=1;e=1; f=1; g=1; h=1;
}
if(!key3)
{ a=0;b=0;c=0;d=1;e=1; f=1; g=1; h=1;
timer0h=FREQH[7*k-5];
timer0l=FREQL[7*k-5];
int0();
while (key3==0);
TR0=0; delay(0.3); a=1;b=1;c=1;d=1;e=1; f=1; g=1; h=1;
}
if(!key4)
{ a=0;b=0;c=0;d=0;e=1; f=1; g=1; h=1;
timer0h=FREQH[7*k-4];
timer0l=FREQL[7*k-4];
int0();
while (key4==0);
TR0=0; delay(0.3); a=1;b=1;c=1;d=1;e=1; f=1; g=1; h=1;
}
if(!key5)
{ a=0;b=0;c=0;d=0;e=0; f=1; g=1; h=1;
timer0h=FREQH[7*k-3];
timer0l=FREQL[7*k-3];
int0();
while (key5==0);
TR0=0; delay(0.3); a=1;b=1;c=1;d=1;e=1; f=1; g=1; h=1;
}
if(!key6)
{ a=0;b=0;c=0;d=0;e=0; f=0; g=1; h=1;
timer0h=FREQH[7*k-2];
timer0l=FREQL[7*k-2];
int0();
while (key6==0);
TR0=0; delay(0.3); a=1;b=1;c=1;d=1;e=1; f=1; g=1; h=1;
}
if(!key7)
{ a=0;b=0;c=0;d=0;e=0; f=0; g=0; h=1;
timer0h=FREQH[7*k-1];
timer0l=FREQL[7*k-1];
int0();
while (key7==0);
TR0=0;delay(0.3); a=1;b=1;c=1;d=1;e=1; f=1; g=1; h=1;
}
if(!key8)
{ a=0;b=0;c=0;d=0;e=0; f=0; g=0; h=0;
timer0h=FREQH[7*k];
timer0l=FREQL[7*k];
int0();
while (key8==0);
TR0=0;delay(0.3); a=1;b=1;c=1;d=1;e=1; f=1; g=1; h=1;
}
}
}
程序说明:
先复位,选用计时器T0,P1口作为输入,然后进行键盘消抖,判断哪个音符键按下,然后跳转到KEY,KEY子程序块是判断低音、中音、高音三个键之一是否按下,然后跳转到相应的子程序,输出P2.7置高电平。
感悟:
通过这次课程设计,最大的收获就是绝大部分都是自己做出来的,不像以前很多都只是差不多相当于一个焊接工。从着手设计开始,到最终调试成功总共花了两周时间,从开始的选题,到查资料查看可行性,到最后成功无处不充满了我的期待。选择电子琴是因为我喜欢音乐、但在做板的途中发现了很多问题。首先,在protel画图中出现了很多错误,不断排查后终于解决了。但在制版之后第一次接电源后没有一点响应,确实心里凉了半截。进过对电路查询,对引脚电压测量发现晶振的振荡回路没有震荡。上网查询后发现,振荡回路应当尽量接近xtal1,2脚。在改进之后通过烧进一个流水灯程序后发现单片机工作正常,但蜂鸣器却不能发声。三极管驱动不了无源蜂鸣器,后面换了ULN2003驱动芯片,蜂鸣器就可以工作了。由于不断地尝试不断地改线,所以原本干净的电路板多了很多根跳线。软件方面尝试了很多,首先用了汇编语言,可是很多次更改也不能实现功能,后面选择了c语言,大概读懂意思之后,通过修改实现了自己想要的功能。总之,这次课程设计让我学到了很多东西,软件硬件知识都得到提高,通过两周的时间,不断的失败,不断地修改,终于成功了。
15
展开阅读全文