您的当前位置:首页正文

南邮-课程设计-可存储式电子琴

2024-09-10 来源:欧得旅游网


通达学院

2013 /2014 学年 第 一 学期

课程设计 实验报告

模 块 名 称 AVR单片机课程设计(proteus) 专 业 学 生 班 级 学 生 学 号 学 生 姓 名 指 导 教 师

设计题目 基于LM016L显示的可存储式电子琴 1、使用4*4键盘,对应2个8度的16个单音,当按下相应按键时,任务要求 扬声器发出相对音符的音阶。 2、可以单键按下,也可以按照乐谱演奏音乐。 3、在ATmega128内存储至多64个单音(在两个8度音阶中任选),按键可以控制开始连续播放这64个单音或停止播放,每个单音的播放时长自定。 4、使用LED/LCD来实时显示目前正在演奏的单音码,例低音音符la、相应的音符频率及时长、或中音音符si、相应的音符频率及时长等。 设备:计算机 实验设备软件:proteus7.7 sp2 ICCAVR7.22 及软件 同组人员 学号及姓名 航空参考文献 [1] 金钟夫 杜刚.ATmega128单片机C程序设计与实践[M].北京:航天大学出版社,1999. [2] 沈建良 赵文宏.ATmega128单片机入门与提高[M].北京:航空航天大学出版社,2001. [3] 张毅刚.单片机应用设计[M].哈尔滨:工业大学出版社,2004年第二版 [4] 长沙太阳人电子有限公司.SMC1602A LCM 使用说明书[EB/OL]. [5] 刘娟 梁卫文.单片机c语言与protues仿真技能实训[M].中国电力出版社,2004. 一人一组,无同组成员 AVR单片机软件设计(proteus)报告

1)总体设计原理、思路

1. 电子琴的设计主要分为手动弹奏乐曲和自动播放音乐两大部分组成。手动弹奏乐曲是根据具体的硬件键盘设置了16个音符按键和1个功能转换键,自动播放音乐是在单片机的存储器中通过软件编程的方法放置音乐代码和相关播放程序来实现。

2. 应用到的原件,主要是ATmega128单片机、矩阵4×4键输入电路、LM016L显示电路、扬声器以及电源电路。 3. 从声音原理方面来看,通过控制单片机的定时器的定时时间产生不同频率的音频脉冲,经放大后驱动扬声器发出不同音乐的声音。用软件延时来控制发音时间的长短,控制节拍。 4. 在写程序时,将电子琴的设计采用程序模块化设计方法,将程序分为主程序、键盘扫描程序模块、数码显示模块。这样使得思路更加清晰,出问题更加容易更正。

2)硬件方面原理图的设计:

整个硬件部分主要包括一颗atmega128单片机,lm016l显示器和16个按键组成。单片机ATMEGA128是一颗高性能低功耗的avr 8位微处理器,它拥有先进的RISC结构,多达133条指令,大多数可以在一个时钟周期内完成。 Atmega128的引脚图

LM016L的接口说明

最后连接的原理图

3)软件方面程序流程图的设计、关键代码的说明

程序流程图如下

关键代码及其说明

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

#include #include //1602液晶显示程序 #include\"xianshi.h\" //蜂鸣器

#define BEEP() PORTB ^= (1<//音符延时表,它们分别对应于0~15号音符的输出频率 uint tone[]=

{64021,64103,64260,64400,64524,64580,64684,64777, 64820,64898,64918,64938,64958,64978,64998,65100 };

//第一段(Tone为音符,Time为节拍) uchar Music1_Tone[] =

{ 2,3,1,1,2,3,1,1,2,3,5,5,5,6,1,1,6,1,2,2,2,1,6,6,6,1,2,2,3,2,1,2,2,2,0xFF }; uchar Music1_Time[] =

{ 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,2,2,2,2,2,0xFF }; //第二段

uchar Music2_Tone[] =

{ 1,3,3,3,3,5,4,2,5,3,7,6,5,5,7,4,4,3,6,7,2,1,0xFF }; uchar Music2_Time[] =

{ 2,1,1,2,1,1,1,2,1,1,3,2,1,1,2,4,1,1,2,1,1,1,0xFF }; //第三段

uchar Music3_Tone[] =

{ 0,1,2,3,4,5,5,6,7,8,9,10,11,12,13,14,15,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0xFF}; uchar Music3_Time[] =

{ 1,1,1,1,1,1,1,1,1,1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1,1,1,1,0xFF};

//第四段

uchar Music4_Tone[] =

{ 0,1,2,3,4,5,5,6,7,8,9,10,11,12,13,14,15,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0xFF}; uchar Music4_Time[] =

{ 1,1,1,1,1,1,1,1,1,1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1,1,1,1,0xFF}; //----

uint playhz=0; uint playtime=0; uchar playn=0; uchar reshbz=0; //自弹

uchar diy[] ={0,3,5,7,9,11,13,14,15}; uchar diyTime[] ={2,2,2,2,2,2,2,2,2}; //音乐符号引用变量 volatile uchar t = 0; volatile uchar i = 0; //播放模式

volatile uchar play=0; //播放模式启动

volatile uchar bz=0; //播放模式静音

volatile uchar bz1=0; //播放曲目1 void play1() {

t=Music1_Tone[i];

if(Music1_Tone[i]==0xff){i=0;TIMSK=0X00;_delay_ms(100);} TIMSK=(1<_delay_ms(Music1_Time[i]*200); playn=Music1_Tone[i];

playhz=tone[Music1_Tone[i]]; playtime=Music1_Tone[i]*200; TIMSK=0X00; i=i+1; }

//播放曲目2 void play2() {

t=Music2_Tone[i];

if(Music2_Tone[i]==0xff){i=0;_delay_ms(1000);} TIMSK=(1<_delay_ms(Music2_Time[i]*200); playn=Music2_Tone[i];

playhz=tone[Music2_Tone[i]]; playtime=Music2_Tone[i]*200; TIMSK=0X00; i=i+1; }

//播放曲目3 void play3() {

t=Music3_Tone[i];

if(Music3_Tone[i]==0xff){i=0;_delay_ms(1000);}

TIMSK=(1<_delay_ms(Music3_Time[i]*200); playn=Music1_Tone[i];

playhz=tone[Music3_Tone[i]]; playtime=Music3_Tone[i]*200; TIMSK=0X00; i=i+1; }

//播放曲目4 void play4() {

t=Music4_Tone[i];

if(Music4_Tone[i]==0xff){i=0;_delay_ms(1000);} TIMSK=(1<_delay_ms(Music4_Time[i]*200); playn=Music4_Tone[i];

playhz=tone[Music4_Tone[i]]; playtime=Music4_Tone[i]*200; TIMSK=0X00; i=i+1; }

//播放DIY void diymusic() {

TIMSK=0X00;

if(!(key==20)) {

t=key;

TIMSK=(1<playhz=tone[playn]; playtime=(key+1)*40; _delay_ms(600); key=20; }

if(playn>20)playn=0; }

void resh1() {

//显示hz:00000 t:00000

lcd1602_adr(0x00); lcd1602_writenumber('h'); lcd1602_adr(0x01); lcd1602_writenumber('z'); lcd1602_adr(0x02); lcd1602_writenumber(':');

lcd1602_adr(0x03); lcd1602_writenumber(0x30+playhz/10000);

lcd1602_adr(0x04); lcd1602_writenumber(0x30+playhz%10000/1000); lcd1602_adr(0x05); lcd1602_writenumber(0x30+playhz%1000/100); lcd1602_adr(0x06); lcd1602_writenumber(0x30+playhz%100/10); lcd1602_adr(0x07); lcd1602_writenumber(0x30+playhz%10); lcd1602_adr(0x09); lcd1602_writenumber('t'); lcd1602_adr(0x0a); lcd1602_writenumber(':');

lcd1602_adr(0x0b); lcd1602_writenumber(0x30+playtime/10000);

lcd1602_adr(0x0c); lcd1602_writenumber(0x30+playtime%10000/1000); lcd1602_adr(0x0d); lcd1602_writenumber(0x30+playtime%1000/100); lcd1602_adr(0x0e); lcd1602_writenumber(0x30+playtime%100/10); lcd1602_adr(0x0f); lcd1602_writenumber(0x30+playtime%10); //显示music:00

lcd1602_adr(0x40); lcd1602_writenumber('m'); lcd1602_adr(0x41); lcd1602_writenumber('u'); lcd1602_adr(0x42); lcd1602_writenumber('s'); lcd1602_adr(0x43); lcd1602_writenumber('i'); lcd1602_adr(0x44); lcd1602_writenumber('c'); lcd1602_adr(0x45); lcd1602_writenumber(':');

lcd1602_adr(0x46); lcd1602_writenumber(0x30+playn%100/10); lcd1602_adr(0x47); lcd1602_writenumber(0x30+playn%10);

lcd1602_adr(0x49); lcd1602_writenumber('p'); lcd1602_adr(0x4a); lcd1602_writenumber('l'); lcd1602_adr(0x4b); lcd1602_writenumber('a'); lcd1602_adr(0x4c); lcd1602_writenumber('y'); lcd1602_adr(0x4d); lcd1602_writenumber(':');

lcd1602_adr(0x4e); lcd1602_writenumber(0x30+play%100/10); lcd1602_adr(0x4f); lcd1602_writenumber(0x30+play%10); }

//主函数

void main(void) {

//端口配置

DDRA=0x00; PORTA=0xff; DDRB=0xff; PORTB=0xff;

DDRC=0x00; PORTD=0xff; DDRD=0xf0; PORTD=0xff;

DDRE=0X00; PORTE=0xff; DDRD&=~(1<<0); EICRA=0X02; EIMSK=0X01; //延时 s_ms(50);

//1602初始化 LcdInit();

TCCR1B=0X01; //T1预设 SEI(); //开中断 play=0; while(1) {

//获取按键值

if(play==0)key=keynumber(); if(play==0)diymusic(); resh1();

if(key1)bz1=1; if(key2)bz1=0;

//-------------------------- if((!(play==0))&&(bz1==0)) {

//显示不同的界面 if(play==1)play1(); if(play==2)play2(); if(play==3)play3(); if(play==4)play3(); } } }

//定时器1溢出中断服务函数用于产生频率实现音乐符 #pragma interrupt_handler timer1_ovf_isr:15 void timer1_ovf_isr(void)// T/C1溢出中断 {

if(t==0xff)return; TCNT1=tone[t]; if(bz1==0)BEEP(); }

#pragma interrupt_handler INT0_ovf_isr:2

void INT0_ovf_isr(void)// {

play=(play+1)%5;i=0;

}#define uchar unsigned char #define uint unsigned int #include\"key.h\" #define RS 5 #define RW 6 #define EN 7

#define RS0 PORTD &=~(1<#define out() DDRC=0XFF;PORTC=0X00; #define in() DDRC=0X00;PORTC=0XFF;

#define out_p PORTC #define in_p PINC

//查忙

void busy(void) {

uchar temp; s_ms(1); RS0 s_ms(1); RW1 s_ms(1); while(temp) { EN1 s_ms(1); in(); s_ms(1); temp = PINC&0x80; //读取A口 s_ms(1); out(); s_ms(1); EN0

s_ms(1); } }

//写指令

void writecom(uchar com) {

busy(); s_ms(1); RS0 s_ms(1); RW0 s_ms(1); EN1 s_ms(1);

out_p=com; //输出指令 s_ms(1); EN0 s_ms(1); }

//1602初始化

void LcdInit(void) {

out()

writecom(0x38); s_ms(1000); writecom(0x01); s_ms(1000); s_ms(1000); writecom(0x02); s_ms(100);

writecom(0x06); s_ms(100);

writecom(0x0c); s_ms(100);

writecom(0x38); s_ms(100); }

//写数据

void lcd1602_writenumber(uchar data) {

busy();

s_ms(1); RS1 s_ms(1); RW0 s_ms(1); EN1 s_ms(1);

out_p = data; //输出数据 s_ms(1); EN0 s_ms(1); }

void lcd1602_adr(uchar dat) {

writecom(0x80 | dat); }

//lcd1602_adr(0x00); lcd1602_writenumber('n'); //lcd1602_adr(0x01); lcd1602_writenumber('u');

//lcd1602_adr(0x02); lcd1602_writenumber('m');void s_ms(uint ms) {

for(;ms>1;ms--); }

void _delay_ms(uint i) {

uchar j; for(;i>0;i--) {

for(j=0;j<1000;j++); } }

void _delay_us(uint i) {

uchar j; for(;i>0;i--) {

for(j=0;j<1;j++); } }

#define key1 ((PIND & (1<<1))==0X00) #define key2 ((PIND & (1<<2))==0X00) uchar key=20; uchar keybz;

uchar keynumber() {

DDRA = 0xf0;//高四位输出,低四位输入 PORTA= 0x0f;

if ((PINA & 0x0f)!=0x0f) {

switch (PINA) { case 0b00001110: key=0; break;//记录输出PINB case 0b00001101: key=1; break; case 0b00001011: key=2; break; case 0b00000111: key=3; break; } DDRA = 0x0f;//高四位输入、低四位输出 PORTA= 0xf0; _delay_ms(5); switch (PINA) { case 0b11100000: key+=0; break;//记录输出PINB case 0b11010000: key+=4; break; case 0b10110000: key+=8; break; case 0b01110000: key+=12;break; } }

return key; }

4)调试过程,最终的实现结果分析

当所有原件连接完成之后,按左下角的运行按钮就会出现运行结果。如果出现问题,首先应当检查原件连接是否有问题,特别是接地和电源,在保证连接无问题的情况下,检查单片机中烧录的c语言文件语法是否有错误,这个过程需要细心的检查。

成功运行后的结构如图

当按下某个键位之后会产生一下结果

其中“hz”表示声音频率,“t”表示发声时间,“music”表示声音编号, “play”表示预存的歌曲编号。

5)心得体会

这次实验,使我初步了解了proteus进行单片机的仿真,学会了proteus仿真软件的基本使用,能够在摸索中进行仿真的流程。获益匪浅。

在本次试验中我发现,想要做好这次实验,就必须在做实验前,最迟上实验课前,一定要把本次实验的内容好好了解一下,这是做实验的基础,否则就会不知道怎么做这次实验,完全的一头雾水。做实验时,一定要仔细看电脑中proteus教程的,务必要将每个步骤,弄清楚,才能了解这个软件的基本操作。总之,这次实验,使单片机原理及应用这门课的一些理论知识与实践相结合,更加深刻了我对这门课的认识,巩固了我的理论知识。

设计成绩评定

评分内容 上机时间 报告审阅结果 原理 完成情况 操作 具体要求 上机时间是否达到要求的学时,按照实际情况给与一定的成绩。 报告结构严谨,文字通顺,用语符合技术规范,图表清楚,书写格式规范,不与别人雷同。 原理清楚,能较好地理解课题任务并提出实施方案。 独立完成规定设计任务,论证、分析、设计、计算、结构、建模、实验正确合理,有一定的创新。 能熟练操作相关工具软件,并利用工具软件完成设计任务。 总分 10分 30分 20分 30分 10分 100分 评分 验收结果 总成绩(五分制) 指导教师评阅意见

注:放最后一页

因篇幅问题不能全部显示,请点此查看更多更全内容