资源描述
智能电子技术实践论文
智能电子技术实践 课程设计
简易电子琴设计
目录
第1章 课程设计任务及要求 2
1.1 设计任务 2
1.2 设计要求 2
第2章 系统硬件设计 2
2.1 基本要求 2
2.2 硬件构成 2
第3章 系统软件设计 3
3.1 设计方案 3
3.2 电路原理 4
3.3按键识别与音符: 5
3.4 系统流程图 5
第4章 调试过程 7
4.1实验步骤: 7
4.2 硬件测试 7
第5章 成果 7
5.1 实验现象: 7
5.2 实物图片: 8
第6章 总结 8
第1章 课程设计任务及要求
1.1 设计任务
1.1.1 任务
设计一个单片机为核心,可演奏3和弦的,音程为三组(G~A)的电子琴。
1.2 设计要求
1.2.1要求
(1)利用所给开关1,2,3,4,5,6,7,8八个键,能够用喇叭发出1、2、3、4、5、6、7、i。
(2) 要求按下按键发声,松开延时一段时间停止。
(3) 中间再按别的键则发另一音调的声音。
第2章 系统硬件设计
2.1 基本要求
根据设计题目要求,该系统需要涉及如下几个方面:
(1)电源部分
(2)单片机部分
(3)音频功放部分
(4)扬声器、键盘部分
1.电源部分设计
由于本系统构造简单,使用5v稳压电供电即可。
2.单片机部分设计
2.2 硬件构成
2.1.1 STC12C5A60S2单片机
图1-1 STC12C5A60S2单片机引脚图
2.1.2 引脚介绍
P0.0—P0.7(39—32):P0口是一个漏极开路型准双向I/O口。在访问外部存储器时,它是分时多路转换的地址(低8位)和数据总线,在访问期间激活了内部的上拉电阻。在EPROM编程时,它接收指令字节,而在验证程序时,则输出指令字节。验证时,要求外接上拉电阻。
P1.0—P1.7(1-8):P1口是带内部上拉电阻的8位双向I/O口。在EPROM编程和程序验证时,它接收低8位地址。
P2.0—P2.7(21-28):P2口是一个带内部上拉电阻的8位双向I/O口。在访问外部存储器时,它送出高8位地址。在对EFROM编程和程序验证期间,它接收高8位地址。
P3.0—P3.7(10-17):P3口是一个带内部上拉电阻的8位双向I/O口。
第3章 系统软件设计
3.1 设计方案
3.1.1 音乐产生原理
所谓音频是指人耳所能听到的频率范围,为20Hz到20KHz。音乐中的音高一般以中央A为基准,其频率为440Hz,一个八度音程的频率关系为2倍的关系。一个八度中间有12个半音,2个半音之间相差(2)^1/12倍。所以,每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0来产生这样方波频率信号,因此,我们只要把相应音阶对应频率关系弄正确即可。
根据A到 A之间每半程音高频率分配如下:
A
#A
B
#B
110.000000
116.540940
123.470825
130.812783
C
#C
D
#D
138.591315
146.832384
155.563492
164.813778
E
#F
G
#G
174.614116
184.997211
195.997718
207.652349
A
#A
B
#B
220.000000
233.081881
246.941651
261.625565
C
#C
D
#D
277.182631
293.664768
311.126984
329.627557
E
#F
G
#G
349.228231
369.994423
391.995436
415.304698
A
#A
B
#B
440.000000
466.163762
493.883301
523.251131
C
#C
D
#D
554.365262
587.329536
622.253967
659.255114
E
#F
G
#G
698.456463
739.988845
783.990872
830.609395
表1-1
所以,系统设计的主要任务既是当某个音高的键盘按下时,在扬声器中发出相应频率的声音即可。
3.1.2 方案设计
具体过程:当系统扫描到键盘上有键子被按下,则快速检测出是那一个键子,然后单片机的定时器被启动,发出一定频率的脉冲,该频率的脉冲经喇叭驱动电路放大滤波后,就会发出相应的音调。如果在前一个按下的键发声的同时有另一个键被按下,则启用中断系统,前面键的发音停止,转到后按的键的发音程序,发出后按的键的音。
3.2 电路原理
音阶由不同频率的方波产生,音阶与频率的关系如下表所示:
音调
1
2
3
4
5
6
7
i
频率(Hz)
262
294
330
349
392
440
494
523
X(Hex)
F921
F9E1
FA8C
FAD8
FB68
FBE9
FC5B
FC8F
表1-2
方波的频率由定时器控制。定时器计数溢出后,产生中断,将P1.0取反既得周期方波。每个音阶相应的定时器初值X可按如下方法计算:
(1/2)*(1/f)=(12/fosc)*(216-X) 即X=216-(fosc/24f)
当晶振fosc=11.0592NHz时,音阶“1”相应的定时器初值为X,则可得X=63777D=F921H,其他的可同样求的。
3.3按键识别与音符:
(1) 8个按钮键盘识别: (2)不同音符产生的方法
图1-2 扬声器图
3.4 系统流程图
分析各项设计要求后,可绘制如下程序流程图
图1-3
第4章 调试过程
4.1实验步骤:
把已经编写且编译仿真通过的原理图下载到芯片上,按引脚图接好芯片的输入和输出,观察实验现象。然后插上电源。
4.2 硬件测试:
刚下载成功后,插上电源,扬声器无响应。经过检查是扬声器正负极接错,改正重新下载。接通电源后扬声器先响一段时间,停止后,按下八个按键无回应。经过检查未发现原因出在何处。电路电压和元器件一切正常。最后检查软件程序,确定问题出现在按键程序上,通过改动,最后测试扬声器发出1234567i八个音阶。
第5章 成果
5.1 实验现象:
插上电源,每按一次按键扬声器都能发出相应的声音来。按一个键后,延时一段时间后,按下一个键则发出另一个音节。实验时一次只能按一个按键,若同时按几个按键,可能得不到想要的结果。依次按键时,可以听到哆唻咪发唢喇嘻哆的声音。
5.2 实物图片:
第6章 总结
本次课程设计,我们选择的是八音电子琴的设计,根据要求该课程需达到以下要求即:可通过键盘输入来控制扬声器;使扬声器能发出1234567i八个音阶。
这次实验总共经历了两周的时间,从功能需求分析到功能分析,从程序的设计到程序的调试,下载,最后终于完成了这次具有实际使用价值的实验。
课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,大规模芯片已经成为当今计算机应用中空前活跃的领域, 在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握开发技术是十分重要的。
通过本次实验,我不仅可以巩固了以前所学过的知识,如数电知识,系统设计和VHDL语言,而且学到了很多在书本上所没有学到过的知识,如实践经验,操作技巧。我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,光看书不进行相关的练习是行不通的,只有把所学的理论知识与实践相结合起来,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,通过这次课程设计之后,把以前所学过的知识重新温故,全部整合,进一步深刻理解。在设计一个具有某功能电路时,第一步也是最真要的一步,做出整个系统的方框图,并确定这个方案可行,再把其中的某个特定功能的模块分开来设计,分别编写,编译仿真,最后再把各个模块按系统方框图连接起来。当某个功能没实现时,就去重点检查那个功能的模块。下载到芯片上具体实现电路功能时,一定要细心耐心,仔细真实的记录下实验现象,并多次检验,这样才能更好的分析自己设计的电路的优点和不足,并进一步的加以改进。这次实验中由于自己准备不足而留下了些遗憾,但总体还是好的,知识的运用与发挥就在于自己平时所得到和积累下来的,我们要学会学习的能力,能够举一反三,触类旁通,这样对于自己以后的发展是很有帮助的,因此我们需要在学习中学习,在实践中找出答。
附录1 电路整体图
附录2 课程程序代码
//---电子音调实验---
//-----头文件引用-----
#include<reg51.h>
#include<absacc.h>
#include<intrins.h>
//-----宏声明-----
#define uchar unsigned char
sfr P1ASF=0x9D;
sfr ADC_CONTR = 0xbc;
sfr ADC_RES = 0xbd;
sfr ADC_RESL= 0xbe;
void GET_AD_Result();
void AD_init( );
//-----变量定义-----
uchar fh,fl; //定义频率高低位变量
sbit BEEP=P3^3;
uchar key_b,i; //键值
uchar time_flag; //8ms标志
uchar key_flag,temp1,temp2,no_key; //AD采样次数,键值采样次数
uchar code f[]={0xFC,0x8F,0xFC,0x5B,0xFB,0xE9,0xFB,0x68, //音阶频率表i,7,6,5
0xFA,0xD8,0xFA,0x8C,0xF9,0xE1,0xF9,0x21};//4,3,2,1
uchar AD_value;
//-----定时器中断-----
//-----初始化-----
void first()
{
TMOD=0x11; //T0 方式 1
TR1=0; //关 T0
ET1=1;
EA=1; //开中断
}
//******************AD按键*************************************//
//----------------------------------------------------
//----------------------------------------------------
void AD_init( )//void AD_init(uchar AD_port_sel ) //ADC初始化
{
ADC_CONTR|=0x80; //开ADC电源
P1ASF=0x01; //设置P1.0高阻输入方式
ADC_CONTR=0xe8; //启动AD转换
}
//----------------------------------------------------
void GET_AD_Result()//启动AD转换并返回转换值
{
uchar temp;
temp=0x10; //判转换结束标志 ADC_FLAG
temp&=ADC_CONTR;
if ( temp )
{
key_b=ADC_RES; //读取AD数据
ADC_CONTR&=0xe0; //清转换结束标志ADC_FLAG
}
else
{
ADC_RES=0; //清转换数据高8位
ADC_RESL=0; //清转换数据低2位
ADC_CONTR|=0xe8; //启动AD转换 ADC_START
}
}
//----------------------------------------------------
unsigned char scan_key()
{
GET_AD_Result();
if( key_b>=252) return(0);
else if( key_b>=225) return(1);
else if( key_b>=221) return(2);
else if( key_b>=216) return(3);
else if( key_b>=210) return(4);
else if( key_b>=196) return(5);
else if( key_b>=186) return(6);
else if( key_b>=165) return(7);
else if( key_b>=122) return(8);
//----------------------------------------------------
void key()
{
time_flag=0; //8ms定时标志
if ( !key_flag )
{
key_flag=1;
temp1=scan_key();
}
else
{
key_flag=0;
temp2=scan_key();
if (temp2==temp1)
{
if ( temp1==0 ) no_key = 1 ;
else if ( no_key )
{
no_key = 0 ;
switch (temp1)
{
case 1: //z增
{fh=f[14]; //查表,将频率定时器高低位存入变量
fl=f[15];TR1=1;;break; }
case 2: //减
{ fh=f[12]; //查表,将频率定时器高低位存入变量
fl=f[13];TR1=1;;break; }
case 3: //模式
{fh=f[10]; //查表,将频率定时器高低位存入变量
fl=f[11];TR1=1;;break; }
case 4:
{fh=f[8]; //查表,将频率定时器高低位存入变量
fl=f[9];TR1=1;break; }
case 5:
{fh=f[6]; //查表,将频率定时器高低位存入变量
fl=f[7];TR1=1;break; }
case 6:
{fh=f[4]; //查表,将频率定时器高低位存入变量
fl=f[5];TR1=1;break; }
case 7:
{fh=f[2]; //查表,将频率定时器高低位存入变量
fl=f[3];TR1=1;break; }
case 8:
{fh=f[0]; //查表,将频率定时器高低位存入变量
fl=f[1];TR1=1;break; }
default:break;
}
}
}
}
}
//-----主程序-----
main()
{
key_flag=0; //键扫描次数
no_key=1;
P2=0xff;
P0=0xff;
TMOD=0x11;//方式寄存器初值
TH0=(65536-1000)/256;// 定时器0设置初始值1ms中断初始值
TL0=(65536-1000)%256;//
EA=1;
ET0=1;
ET1=1;
TR0=1;//起动定时器0
AD_init( );
first(); //初始化
while(1)
{
if(time_flag) key();
}}
void time0() interrupt 1 using 2//定时器0中断函数
{
TF0=0;//定时器0中断溢出标志清0
TH0=(65536-1000)/256;//定时器0设置初始值1ms中断初始值
TL0=(65536-1000)%256;
i++;
if(i==8){i=0;time_flag=1; }
}
void intt1() interrupt 3
{
TR1=0; //T0 关闭
BEEP=~BEEP;
TH1=fh; //重载定时器
TL1=fl;
TR1=1; //T0 允许
}
14
展开阅读全文