仿真简易电子琴.docx
《仿真简易电子琴.docx》由会员分享,可在线阅读,更多相关《仿真简易电子琴.docx(17页珍藏版)》请在冰点文库上搜索。
仿真简易电子琴
简易电子琴
一:
系统设计要求
简易电子琴拥有16个按键,每个按键按下后都可以发出不同的声音,还有一个按键,按下后可以播放一小段示例音乐。
要求按键采用扫描方式检测哪个按下,并且在七段数码管上显示按下的是哪个按键。
二:
系统结构框图和工作原理
工作原理:
系统上电启动后,首先采用按行扫描的方式查询时哪一个按键被按下,首先扫描第一行,若第一行没有按键按下,继续扫描第二行,依次类推,若扫描到某一行有键按下时,再检测是哪个键按下了,得到结果后,先保存键值,然后进入处理阶段,处理时,首先送七段数码管显示键值。
然后再利用计数器和喇叭实现发声,发声的原理主要利用不同声音有不同频率得到的,具体数据是参考的书上的。
若没有按键按下,当按下音乐控制键时,开始播放音乐,音乐的数据也来自书上,按下停止键音乐停止,具体原理利用发声的频率加一些延时构成。
都没有按键按下时,系统不停地在等待按键的按下。
三:
单元硬件设计说明
(1)时钟电路:
时钟电路由一个12M晶振,和两个3pF电容组成,产生12M赫兹的方波脉冲信号做为单片机的内部时钟。
(2)复位电路和音乐控制电路:
一个5V的电源,一个10KΩ的电阻,一个4KΩ的电阻,一个74LS04,一个10F的电容及连个按键构成。
具体见实际电路图。
(3)显示电路,由7个470R上拉电阻和七段数码管组成。
(4)键盘:
4×4扫描式按键盘构成。
四:
软件设计与说明包括程序流程图以及PROTEUS电路图
1主程序流程
2,显示和发声子程序3音乐播放子程序
PROTEUS电路图
五:
程序
KEYBUFEQU30H
STH0EQU31H
STL0EQU32H
TEMPEQU33H
SPKEQUP1.6;蜂鸣器所在端口
ORG0000H
LJMPSTART
ORG0BH
LJMPINT_T0
START:
MOVTMOD,#01H
SETBET0
SETBEA
WAIT:
MOVP2,#0FFH
CLRP2.4;从第四行开始扫描
MOVA,P2
ANLA,#0FH;屏蔽高四位,高四位为行,低四位为列
XRLA,#0FH
JZNOKEY1;判断是否有键按下,没有就跳转
LCALLDELY10MS
MOVA,P2;消除抖动和干扰
ANLA,#0FH
XRLA,#0FH
JZNOKEY1
MOVA,P2;确定有键按下以后的处理
ANLA,#0FH
CJNEA,#0EH,NK1;是否为第四行第一列的键被按下
MOVKEYBUF,#0;保存列号
LJMPDK1
NK1:
CJNEA,#0DH,NK2
MOVKEYBUF,#1
LJMPDK1
NK2:
CJNEA,#0BH,NK3
MOVKEYBUF,#2
LJMPDK1
NK3:
CJNEA,#07H,NK4
MOVKEYBUF,#3
LJMPDK1
NK4:
NOP
DK1:
;第四行的处理
MOVA,KEYBUF
MOVDPTR,#TABLE
MOVCA,@A+DPTR
MOVP0,A
MOVA,KEYBUF
MOVB,#2;Table1以字保存,所以散转
MULAB
MOVTEMP,A
MOVDPTR,#TABLE1
MOVCA,@A+DPTR
MOVSTH0,A;送入高字节
MOVTH0,A
INCTEMP
MOVA,TEMP
MOVCA,@A+DPTR
MOVSTL0,A;送入低字节
MOVTL0,A
SETBTR0
DK1A:
MOVA,P2;判断按键是否松开
ANLA,#0FH
XRLA,#0FH
JNZDK1A
CLRTR0
NOKEY1:
MOVP2,#0FFH
CLRP2.5
MOVA,P2
ANLA,#0FH
XRLA,#0FH
JZNOKEY2
LCALLDELY10MS
MOVA,P2
ANLA,#0FH
XRLA,#0FH
JZNOKEY2
MOVA,P2
ANLA,#0FH
CJNEA,#0EH,NK5
MOVKEYBUF,#4
LJMPDK2
NK5:
CJNEA,#0DH,NK6
MOVKEYBUF,#5
LJMPDK2
NK6:
CJNEA,#0BH,NK7
MOVKEYBUF,#6
LJMPDK2
NK7:
CJNEA,#07H,NK8
MOVKEYBUF,#7
LJMPDK2
NK8:
NOP
DK2:
MOVA,KEYBUF
MOVDPTR,#TABLE
MOVCA,@A+DPTR
MOVP0,A
MOVA,KEYBUF
MOVB,#2
MULAB
MOVTEMP,A
MOVDPTR,#TABLE1
MOVCA,@A+DPTR
MOVSTH0,A
MOVTH0,A
INCTEMP
MOVA,TEMP
MOVCA,@A+DPTR
MOVSTL0,A
MOVTL0,A
SETBTR0
DK2A:
MOVA,P2
ANLA,#0FH
XRLA,#0FH
JNZDK2A
CLRTR0
NOKEY2:
MOVP2,#0FFH
CLRP2.6
MOVA,P2
ANLA,#0FH
XRLA,#0FH
JZNOKEY3
LCALLDELY10MS
MOVA,P2
ANLA,#0FH
XRLA,#0FH
JZNOKEY3
MOVA,P2
ANLA,#0FH
CJNEA,#0EH,NK9
MOVKEYBUF,#8
LJMPDK3
NK9:
CJNEA,#0DH,NK10
MOVKEYBUF,#9
LJMPDK3
NK10:
CJNEA,#0BH,NK11
MOVKEYBUF,#10
LJMPDK3
NK11:
CJNEA,#07H,NK12
MOVKEYBUF,#11
LJMPDK3
NK12:
NOP
DK3:
MOVA,KEYBUF
MOVDPTR,#TABLE
MOVCA,@A+DPTR
MOVP0,A
MOVA,KEYBUF
MOVB,#2
MULAB
MOVTEMP,A
MOVDPTR,#TABLE1
MOVCA,@A+DPTR
MOVSTH0,A
MOVTH0,A
INCTEMP
MOVA,TEMP
MOVCA,@A+DPTR
MOVSTL0,A
MOVTL0,A
SETBTR0
DK3A:
MOVA,P2
ANLA,#0FH
XRLA,#0FH
JNZDK3A
CLRTR0
NOKEY3:
MOVP2,#0FFH
CLRP2.7
MOVA,P2
ANLA,#0FH
XRLA,#0FH
JZNOKEY4
LCALLDELY10MS
MOVA,P2
ANLA,#0FH
XRLA,#0FH
JZNOKEY4
MOVA,P2
ANLA,#0FH
CJNEA,#0EH,NK13
MOVKEYBUF,#12
LJMPDK4
NK13:
CJNEA,#0DH,NK14
MOVKEYBUF,#13
LJMPDK4
NK14:
CJNEA,#0BH,NK15
MOVKEYBUF,#14
LJMPDK4
NK15:
CJNEA,#07H,NK16
MOVKEYBUF,#15
LJMPDK4
NK16:
NOP
DK4:
MOVA,KEYBUF
MOVDPTR,#TABLE
MOVCA,@A+DPTR
MOVP0,A
MOVA,KEYBUF
MOVB,#2
MULAB
MOVTEMP,A
MOVDPTR,#TABLE1
MOVCA,@A+DPTR
MOVSTH0,A
MOVTH0,A
INCTEMP
MOVA,TEMP
MOVCA,@A+DPTR
MOVSTL0,A
MOVTL0,A
SETBTR0
DK4A:
MOVA,P2
ANLA,#0FH
XRLA,#0FH
JNZDK4A
CLRTR0
NOKEY4:
JNBP1.0,MUSIC
LJMPWAIT
MUSIC:
MOVR3,#00H
NEXT:
MOVA,R3
MOVDPTR,#TABLE2
MOVCA,@A+DPTR
JZMUSIC;如果检测到0000时,再执行一遍
MOVR7,A
INCR3
MOVA,R3
MOVCA,@A+DPTR
MOVR2,A
ACALLSONG
INCR3
SJMPNEXT
;===歌曲播放子程序===
SONG:
MOVA,R2;取出节拍
RLA
JNZKEEP
MOVA,#01H
KEEP:
MOVR2,A
REPEAT:
ACALLEIGHTH
DJNZR2,REPEAT
RET
;===产生1/8拍延时子程序===
EIGHTH:
MOVA,R7;查表取出廷时参数,保存到R4
MOVDPTR,#DELAY_T
MOVCA,@A+DPTR
MOVR4,A
MOVA,R7;查表取出1/8拍周期数,保存到R5
MOVDPTR,#S_PARA
MOVCA,@A+DPTR
MOVR5,A
NEXTCYC:
ACALLSOUND
DJNZR5,NEXTCYC
RET
;===发声子程序===
SOUND:
SETBSPK
ACALLSDELAY
CLRSPK
ACALLSDELAY
RET
;===延时子程序===
SDELAY:
MOVA,R4;廷时值在R4内
MOVR0,A
XL2:
MOVR1,#03H
DL1:
NOP
DJNZR1,DL1
DJNZR0,XL2
RET
;===1/8拍周期表===
S_PARA:
DS1DH
DB15H,16H,00
DB19H,00H,1CH,00H,1FH,21H,00H,25H
DB00H,29H,2CH,00H,31H,34H,37H,00H
DB3EH,41H,00H,49H,00H,52H,57H,00H
DB62H
;===延时参数表===
DELAY_T:
DS1DH
DB7EH,77H,00H
DB6AH,00H,5EH,00H,54H,4FH,00H,46H
DB00H,3FH,3BH,00H,35H,32H,2FH,00H
DB2AH,27H,00H,23H,00H,1FH,1DH,0C0H
DB1AH
DELY10MS:
MOVR6,#10
D1:
MOVR7,#248
DJNZR7,$
DJNZR6,D1
RET
INT_T0:
MOVTH0,STH0
MOVTL0,STL0
CPLP1.6
RETI
TABLE:
DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H
DB7FH,6FH,77H,7CH,39H,5EH,79H,71H
TABLE1:
DW64021,64103,64260,64400
DW64524,64580,64684,64777
DW64820,64898,64968,65030
DW65058,65110,65157,65178
;===歌曲表===
TABLE2:
DW2202H,2902H,2902H,2902H,2906H,2702H;我从山中来
DW2502H,2702H,2502H,2402H,2208H;带着兰花草
DW2E02H,2E02H,2E02H,2E02H,2E06H,2C02H;种在小园中
DW2902H,2C02H,2D02H,2A02H,2908H;祈祷花开早
DW2902H,2E02H,2E02H,2C02H,2906H,2702H;一日看三回
DW2502H,2702H,2502H,2402H,2206H,1D02H;看得花时过
DW1D02H,2502H,2502H,2402H,2206H,2902H;兰花却依然
DW2702H,2502H,2402H,2002H,2208H;苞也无一个
DW0000H;
END
六:
调试与运行
程序写完后,存在一些缺点和错误,经过调试后,能正常发声,但是不能显示键值,经过和同学探讨发现用错了数码管,最后把数码管改成共阴极后,终于也能显示键值了。
而且在运行歌曲时,由于CPU不够用,导致发声的时候失真。
运行仿真结果: