基于某8086地简易电子琴设计附总汇编源程序.docx
《基于某8086地简易电子琴设计附总汇编源程序.docx》由会员分享,可在线阅读,更多相关《基于某8086地简易电子琴设计附总汇编源程序.docx(28页珍藏版)》请在冰豆网上搜索。
![基于某8086地简易电子琴设计附总汇编源程序.docx](https://file1.bdocx.com/fileroot1/2023-6/7/ada46222-6346-4d3c-91e5-b324d1495c4e/ada46222-6346-4d3c-91e5-b324d1495c4e1.gif)
基于某8086地简易电子琴设计附总汇编源程序
《微机原理与接口技术》
综合设计实验报告
设计课题:
基于8086的简易电子琴设计
指导老师:
学生:
学号:
院系:
专业:
通信工程
基于8086的简易电子琴设计
摘要
在学习《微机原理与接口设计》的基础上,针对课程设计要求,综合运用相关软件、硬件知识,设计一个简易电子琴,使之具有音区切换、数码管显示音区及当前音符、记录音符与音符持续时间、播放录制的音乐等功能。
关键词:
8086;电子琴;仿真调试;汇编
第1章总体方案设计
1.1系统整体架构图
系统整体架构图如图1-1所示。
图1-1
1.2功能介绍
本实验设计实现了音区切换、数码管显示当前音区及音符、记录音符与音符持续时间、播放录制的音乐等功能。
功能具体说明如下。
按键0-6为音符键,按下后会有对应的音符音调响起,按键弹起后音符终止,此时,按下的音符以及时间将被记录。
按键12,13,14可以选择低音,中音,高音区。
按下按键15后开始播放录制的音符(不超过16个)。
另外数码管0显示音符,数码管2显示音区。
第2章硬件设计
2.1硬件资源
TD-PITE实验教学系统,其主要系统构成如表2-1所示。
CPU
Intel386EX
存储器
系统程序存储器:
FlashROM(128KB)
数据存储器:
SRAM(128KB)
信号源
单次脉冲:
消抖动脉冲2组
逻辑电平开关与显示
16组电平开关,16组电平显示LED灯(正逻辑)
8259、8237、8254、8255、8251、DAC0832、ADC0809、SRAM、键盘扫描及数
接口实验单元
码管显示、电子发声、点阵LED、液晶LCD(可选)、步进电机(可选)、直流电
机、温度控制
实验扩展单元
2组40线通用集成电路扩展单元、扩展模块总线单元
系统电源
+5V/2A,±12V/0.2A
表2-1TD-PITE系统构成
系统硬件结构如图2-1所示。
图2-1
2.2硬件接线图
2.2.18254接线图
8254芯片接线如图2-2所示。
图2-2
2.2.28255及键盘、数码管接线图
8255及键盘、数码管接线方法如图2-3所示。
图2-3
第3章软件设计
3.1程序框图
3.1.1整体框图
图3-1
3.1.2延时函数
图3-2
3.1.3键盘扫描
图3-3
3.1.4数码管显示
图3-4
3.1.5声音及时间录制
图3-5
3.1.6选择音区(高、中、低)
图3-6
3.1.7播放音乐
图3-7
第4章实验结果及演示
具体演示效果可扫描以下二维码进行观看,二维码如图4-1所示。
图4-1
以下为视频截图。
系统初始运行状体如图4-2所示。
图4-2
选择中音区,如图4-3所示。
图4-3
按下音符健,如图4-4所示。
图4-4
音乐播放,如图4-5所示。
图4-5
第5章遇到的问题及改进措施
5.1条件转移指令报错
在编写程序时曾多次遇到使用条件转移指令时编译出错的情况。
查阅书本后发现条件转移指令只能在代码段的-128~+127字节进行跳转。
解决办法:
使用条件转移指令转移到一个较近程序段,并在这程序段使用无条件转移指令JMP进行转移。
5.2无法使用8254作为录音时间计数器
在进行设计的过程中,曾多次按照使用8254作为时间计数器的方案进行编程,但经过多次尝试后均以失败告终。
解决办法:
使用软件延时进行计时,每次延时执行完毕后进行计数,该计数值就是音符的相对持续时间。
在播放时只需要调用同样时间长度的延时函数即可。
缺点:
使用软件延时与计数,占用了CPU计算资源,导致数码管扫描频率降低,亮度变暗。
同时对于录音时间的记录不精确,存在一定的误差。
附录
程序源码
;=======================================================
;文件名:
Hypo.asm
;功能描述:
按键0-6为音符键,按下后会有对应的音调响起,
;按键弹起后音符终止。
;按键12,13,14可以选择低音,中音,高音区。
;按下按键15后开始播放之前按下的音符(不超过16个)
;数码管0显示音符,数码管2显示音区
;=======================================================
IOY3EQU06C0H
MY8254_COUNT0EQUIOY3+00H;8254计数器0端口地址
MY8254_COUNT1EQUIOY3+02H;8254计数器1端口地址
MY8254_COUNT2EQUIOY3+04H;8254计数器2端口地址
MY8254_MODEEQUIOY3+06H;8254控制寄存器端口地址
MY8255_AEQU0600H;8255A端口地址
MY8255_BEQU0602H;8255B端口地址
MY8255_CEQU0604H;8255C端口地址
MY8255_CONEQU0606H;8255控制端口地址
SSTACKSEGMENTSTACK;定义堆栈段
DW256DUP(?
)
SSTACKENDS
DATASEGMENT
DTABLEDB3FH,06H,5BH,4FH,66H,6DH,7DH,07H;数码管的段选数据
DB7FH,6FH,77H,7CH,39H,5EH,79H,71H
FREQ_LIST1DW248,278,312,330,371,416,467;低音频率表
FREQ_LIST2DW495,556,624,661,742,833,935;中音频率表
FREQ_LIST3DW990,1112,1248,1322,1484,1665,1869;高音频率表
REC_DATADW000,000,000,000,000,000,000,000;录音储存段
DW000,000,000,000,000,000,000,000
SBDB00H,00H;过渡段
REC_TIMEDB00H,00H,00H,00H,00H,00H,00H,00H;时间储存段
DB00H,00H,00H,00H,00H,00H,00H,00H
SAVE_SIDW?
;录音储存地址储存
SI_FREQDW?
;频率表地址储存
SAVE_SI_TIMEDW?
;时间储存表地址储存
SAVE_TIMEDB01H;时间技术储存
CHOOSE_FLAGDW01H;频率表选择标志位
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA;初始化数据段、代码段
START:
MOVAX,DATA
MOVDS,AX
MOVDX,MY8254_MODE;初始化8254工作方式
MOVAL,36H;定时器0、方式3
OUTDX,AL
MOVSI,OFFSETREC_DATA;装入录音表初始地址
MOVSAVE_SI,SI
MOVCL,0EH
CLEAN_REC:
;录音表清零
MOVAX,0000H
MOV[SI],AX
ADDSI,2
LOOPCLEAN_REC
MOVSI,OFFSETREC_TIME;装入时间表起始地址
MOVSAVE_SI_TIME,SI
MOVSI,OFFSETFREQ_LIST1;装入频率表默认起始地址
MOVSI_FREQ,SI
MOVSI,3000H
MOVAL,00H
MOV[SI],AL;清显示缓冲
MOV[SI+1],AL
MOV[SI+2],AL
MOV[SI+3],AL
MOV[SI+4],AL
MOV[SI+5],AL
MOVDI,3005H
MOVDX,MY8255_CON;写8255控制字
MOVAL,81H
OUTDX,AL
BEGIN:
CALLDIS;调用显示子程序
CALLDIS_FREQ;调用音区显示子程序
CALLCLEAR;清屏
CALLCCSCAN;键盘扫描
JNZINK1
JMPBEGIN
INK1:
CALLDIS
CALLDALLY
CALLDALLY
CALLCLEAR
CALLCCSCAN
JNZINK2;有键按下,转到INK2
JMPBEGIN
;===============蜂鸣器关闭子程序==================
SILENT:
MOVDX,MY8254_MODE;初始化8254工作方式
MOVAL,36H;定时器0、方式3
OUTDX,AL
RET
;===============远程跳转过渡=================
PLAY2_JUMP:
JMPPLAY2
CHOOSE_JUMP1:
JMPCHOOSE1
CHOOSE_JUMP2:
JMPCHOOSE2
CHOOSE_JUMP3:
JMPCHOOSE3
;========================================
;确定按下键的位置
;========================================
INK2:
MOVCH,0FEH
MOVCL,00H
COLUM:
MOVAL,CH
MOVDX,MY8255_A
OUTDX,AL
MOVDX,MY8255_C
INAL,DX
L1:
TESTAL,01H;isL1?
JNZL2;如果不是的话跳转到L2
MOVAL,00H;L1
JMPKCODE
L2:
TESTAL,02H;isL2?
JNZL3
MOVAL,04H;L2
JMPKCODE
L3:
TESTAL,04H;isL3?
JNZL4
MOVAL,08H;L3
JMPKCODE
L4:
TESTAL,08H;isL4?
JNZNEXT
MOVAL,0CH;L4
;=================================
;确认按键的值
;=================================
KCODE:
ADDAL,CL
CALLPUTBUF
PUSHAX
;=========================
;键值存在AX中
;========================
CMPAX,12;选择音区1
JZCHOOSE_JUMP1
CMPAX,13;选择音区2
JZCHOOSE_JUMP2
CMPAX,14;选择音区3
JZCHOOSE_JUMP3
CMPAX,15;播放录制的音乐
JZPLAY2_JUMP;jumptoplay2
POPAX
PUSHAX
CALLPLAY;播放音符
POPAX
PUSHAX
;=====================
;松手检测
;=====================
KON:
CALLDIS
CALLDIS_FREQ
CALLCLEAR
CALLCNT_TIME;按键没有弹起,执行时间计数
POPAX
PUSHAX
CALLCCSCAN
JNZKON;判断是否弹起,如果没有弹起,继续检测。
;按键弹起后:
CALLSILENT;蜂鸣器静音
MOVSI,SAVE_SI_TIME
MOVAL,SAVE_TIME
MOV[SI],AX;按下的时间进入时间表
INCSAVE_SI_TIME;时间表地址+1
MOVSAVE_TIME,00H;时间计数清零
INCSAVE_SI;录音表地址+1
INCSAVE_SI
POPAX
NEXT:
INCCL
MOVAL,CH
TESTAL,08H
JZKERR
ROLAL,1
MOVCH,AL
JMPCOLUM
KERR:
JMPBEGIN
CNT_TIME:
;时间计数
CALLDALLY3
INCSAVE_TIME
RET
;========================================
;键盘扫描子程序,有按键按下,返回1
;========================================
CCSCAN:
MOVAL,00H
MOVDX,MY8255_A
OUTDX,AL
MOVDX,MY8255_C
INAL,DX
NOTAL
ANDAL,0FH
RET
;========================================
;清屏子程序
;========================================
CLEAR:
MOVDX,MY8255_B
MOVAL,00H
OUTDX,AL
RET
;========================================
;显示子程序
;========================================
DIS:
PUSHAX
MOVSI,3000H;数码管地址
MOVDL,0FEH;数码管位选
MOVAL,DL
AGAIN:
PUSHDX
MOVDX,MY8255_A
OUTDX,AL;数码管位选输出
MOVAL,[SI]
MOVBX,OFFSETDTABLE
ANDAX,00FFH
ADDBX,AX;得到数码管段选数据
MOVAL,[BX]
MOVDX,MY8255_B
OUTDX,AL;数码管段选输出
CALLDALLY
POPDX
MOVAL,DL
MOVDL,AL
JMPOUT1
OUT1:
POPAX
RET
;======延时子程序======
DALLY:
PUSHCX
MOVCX,0006H
T1:
MOVAX,009FH
T2:
DECAX
JNZT2
LOOPT1
POPCX
RET
;========================================
;存键盘值到相应位的缓冲中
;========================================
PUTBUF:
MOV[SI],AL
CMPDI,3005H
JNZGOBACK
GOBACK:
RET
CHOOSE1:
MOVSI,OFFSETFREQ_LIST1;装入频率表1起始地址
MOVSI_FREQ,SI
MOVCHOOSE_FLAG,01H
JMPBEGIN
CHOOSE2:
MOVSI,OFFSETFREQ_LIST2;装入频率表2起始地址
MOVSI_FREQ,SI
MOVCHOOSE_FLAG,02H
JMPBEGIN
CHOOSE3:
MOVSI,OFFSETFREQ_LIST3;装入频率表3起始地址
MOVSI_FREQ,SI
MOVCHOOSE_FLAG,03H
JMPBEGIN
;==========================
;音区数码管显示
;==========================
DIS_FREQ:
PUSHAX
MOVSI,3003H
MOVDL,0FBH
MOVAL,DL
AGAIN1:
PUSHDX
MOVDX,MY8255_A
OUTDX,AL
MOVAL,[SI]
MOVBX,OFFSETDTABLE
ANDAX,00FFH
ADDBX,CHOOSE_FLAG
MOVAL,[BX]
MOVDX,MY8255_B
OUTDX,AL
CALLDALLY
POPDX
MOVAL,DL
MOVDL,AL
JMPOUT2
OUT2:
POPAX
RET
PLAY:
MOVSI,SI_FREQ;装入频率表起始地址
ADDSI,AX
ADDSI,AX
MOVDX,0FH;输入时钟为1MHz,1M=0F4240H
MOVAX,4240H
DIVWORDPTR[SI];取出频率值计算计数初值,0F4240H/输出频率
MOVSI,SAVE_SI;将计数初值存入录音音符段
MOV[SI],AX
MOVDX,MY8254_COUNT0;蜂鸣器播放音符
OUTDX,AL
MOVAL,AH
OUTDX,AL
RET
PLAY2:
MOVSI,OFFSETREC_DATA;装入录音表计数初值起始地址
MOVDI,OFFSETREC_TIME;装入录音时间表起始地址
PLAY2_1:
MOVAX,[SI]
MOVDX,MY8254_COUNT0
OUTDX,AL;装入计数初值并播放
MOVAL,AH
OUTDX,AL
MOVDL,[DI];取出演奏相对时间,调用延时子程序
CALLDALLY2
ADDSI,2
INCDI
CALLSILENT;停止播放0.1秒
CALLDALLY3
CALLDALLY3
CALLDALLY3
CALLDALLY3
CALLDALLY3
CALLDALLY3
CALLDALLY3
CALLDALLY3
CALLDALLY3
CALLDALLY3
CALLDALLY3
CALLDALLY3
CMPWORDPTR[SI],0;判断是否到曲末?
JEXXX;如果来到曲末跳转到开始
JMPPLAY2_1;否则继续播放下一个音符
XXX:
JMPSTART;远程跳转过渡
DALLY2PROC;延时子程序2
D0:
MOVCX,0015H
D1:
MOVAX,00F0H
D2:
DECAX
JNZD2
LOOPD1
DECDL
JNZD0
RET
DALLY2ENDP
DALLY3PROC;延时子程序3
D00:
MOVCX,0010H
D11:
MOVAX,00F0H
D22:
DECAX
JNZD22
LOOPD11
RET
DALLY3ENDP
CODEENDS
ENDSTART