中南大学汇编课程设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中南大学
微机原理课程设计报告——信号发生器功能程序设计
目录
第一章设计题目、要求及目的 (3)
1.设计题目要求 (3)
2.设计目的 (3)
第二章总体设计方案 (3)
1.设计思想 (3)
2.设计方案 (4)
3.总体设计流程图 (5)
第三章硬件设计 (5)
1.硬件环境要求 (5)
2.所用芯片及其功能说明 (6)
3.硬件接线图 (9)
第四章程序设计 (10)
1.流程图 (10)
2.典型程序模块及典型编程技巧分析··13
3.课程设计中遇到的问题及解决方法··14
4.程序清单和程序注释 (15)
第五章收获与体会 (33)
第六章参考文献 (33)
第一章设计题目、要求及目的
1.设计题目及要求
设计题目:信号功能发生器设计
设计要求:
(1)、编程语言为C语言和汇编语言;
(2)、硬件电路基于80x86微机的接口电路;
(3)、程序功能要求:小键盘给定、数码管(屏幕)显示,并产生对应信号波形(D/A)输出(信号波形包括正弦波、三角波、方波、锯齿波)、输出信号波形幅度、频率可调。
(注意:按键数量应尽量少)。
2.设计目的
(1)、熟练掌握汇编语言和C语言,并用它们实现对硬件的操作,实现设计要求。
(2)、学会调试程序,可以通过编译(masm)、链接(link)、运行(run)可以看到汇编程序的运行结果,更多的是要通过Debug来调试以发现程序的逻辑问题,熟练运用Debug可以解决很多问题,如Debug的T命令可以查看单步运行的结果。
(3)、对硬件加深了解,特别是此实验要用到的8255及小键盘等
(4)、本课程设计,要求对微机系统有一个较全面的理解,对典型数字接口电路的应用技术有一个较深入的掌握,并对应用系统进行硬件原理和软件编程进行分析、设计和调试,达到基本掌握简单微型计算机应用系统软硬件的设计方法,提高项目开发能力的目的。
第二章总体设计方案
1.设计思想
该课题要求实现信号功能发生器,首先通过小键盘给定一个按键,并将此信息送入计算机中,由计算机内部根据此信息去实现特定的功能,比如产生正弦波。
计算机在获得小键盘给定的信息之后,送出一个信息到产生波形的芯片0832,由其去实现波形的产生。
要实现数码管显示,则需要将显示的信息通过输入输出端口芯片送到数码管端口。
实现调频和调幅是跟据波形产生的原理改变产生波形的参数即可实现。
从外设送数据进入CPU是通过8255A芯片实现的,波形的产生
由0832实现。
首先我确定了所用到的芯片:8255A和0832,在此实验中通过小键盘的按键来控制信号发生器的各个功能,在实验中采用可编程中断控制器8259A可以简化程序的逻辑便于实现,但8259A在初始化及编写是比较麻烦故而不采用。
为了减少按键,产生四种波形时我采用查询式的方法,即通过一个键控制不同波形的产生,比如按第一下的时候产生正弦波,第二次按键产生三角波,第三次按键产生方波,第四次按键产生锯齿波。
同时通过一个键控释信号功能发生器的开始和停止,第一次按键是开始,第二次按键是结束。
再通过四个按键分别控制波形的幅度增加、幅度减少、频率增减、频率减少。
因此在我的设计总共用到6个键。
如果还要减少键可以把频率增加和幅度增加放在一个键,频率减少和幅度减少放在一个键,此外还有多种实现方法。
小键盘给定主要是确定是哪个键按下,并且要注意消除抖动。
产生波形时,可以通过给定点通过延时产生不同的波形的,对于正弦波通过查表产生波形是最简单的方法,但要注意点的给定。
但是也带来一个问题,正弦波的幅值的产生不能通过通过简单的给每一个点加一个固定的值,这样容易出现两个问题,一是如果给的表中如果出现较大的数值加上一个数值的时候进位舍去,此数值变成一个小的数值,是波形发生畸变。
而是如果每个数值加上一个固定的数值不会使幅值发生变化,只是波形发生了平移,要对正弦波改变幅值需要对个点进行伸缩变化,即要通过乘或除改变其幅值大小。
在此过程中要注意处理溢出及位数的问题。
其他波形的产生比较容易,方波是给定一个最低值和一个最高值,通过延时产生低电平和高电平两个状态,三角波是从一个最低值一直增加到最高值再从最高值一直减少到最低值,锯齿波是从一个最低值一直增加到最高值,然后再从最低值增加到最高值,一直循环。
由此可以看出方波、三角波及锯齿波的幅值改变可以用同一个子程序实现,即改变最高值就可以改变幅值。
相对幅值的改变,频率的改变更简单,频率的改变可以通过改变延时来实现。
要数码管显示,首先要选定显示的数码管,如果要显示一位比较容易,要显示两位则需要注意延时问题,即显示第二位的时候第一位的数据也要确保能显示在数码管上。
2、设计方案
方案选择:1.四种波形的幅度和频率调节采用硬件的方法实现,但由于实验室器材的原因,以及加入很多芯片或是外围电路会使控制过程更麻烦。
2、采用软件的方法实现,虽然加大了编程的难度,但我们可以
在寝室编程,方便和同学们的讨论,同时他不向方案一那样过度依赖硬件。
(1)、总体设计
该阶段主要是通过查阅资料以及讨论确定实现方案,并合理设计软硬件部分 功能,一般来说软件硬件具备一定的互通性,用硬件的有点是可以提高系统的工作速度,但会增加电路的复杂性和硬件成本,用软件可以代替硬件的某些功能使电路简化,但增加了软件的成本,比如在该设计中可以用可编程中断控制器8259A 控制键盘的工作,也可以通过软件编程实现小键盘的给定功能,由于用8259A 产生中断控制电路复杂而且初始化设置不简单,故用软件编程代替。
(2)、硬件设计过程
确定所需要的芯片以及所硬件原理图、连接图 (3)、软件设计过程
画出程序流程图,分模块实现各个部分的功能,并上机实现。
(4)、软、硬件联调
连接电路图,并运行软件,调节硬件并适当地修改软件,实现整体功能。
3.总体设计流程图
第三章 硬件设计
微型计算机总线
键盘给定输入用于选择
DAC 0832输出某种频率波形
微型计算机总线
8255A 可编程外围接口芯片
将数据送给数码管显示
1.硬件环境要求
(1)、唐都(tangdu)仪器硬件环境:
操作系统:
中文Windows98/Me/2000/XP
最低配置
CPU:奔腾400Mhz
内存:16MB
显示卡:标准VGA,256色显示模式以上
硬盘:50MB
驱动器:2X倍速CD-ROM以上
其它设备:鼠标器
建议配置
CPU:奔腾400Mhz或更高
内存:16MB以上
显示卡:SVGA,16K色以上显示模式
(2)、8086、8088的功能简介
Intel 8086 CPU是十六位微处理器。
它采用N-沟道,耗尽型负载的硅栅工艺(HMOS)制造,外形为双列直插式,有40个引脚。
8086CPU有十六根数据线和20根地址线,直接寻址空间为2的十次方,为1MB。
8086有一组强有力的指令系统内部有硬件乘除指令以及串处理指令,可对多种数据类型进行处理。
8086CPU与8位CPU8088向上兼容,处理能力比8080高10倍以上,而相同任务程序代码长度可缩短20%.8086可与8087协处理器及8089输入/输出多处理器构成多机系统,以提高数据处理及输入/输出能力。
8088CPU内部结构与8088基本相同,但对外数据总线只有8条,称为准16微处理器。
2.所用芯片及其功能说明
(1)、AC0832功能简介
芯片介绍:DAC0832是美国数据公司的8位D/A转化器,片内带数据锁存
电流输出,输出电流稳定时间为1μm,功耗为20mW,其引脚说明如下:
D0~D7:数据输入线,TTL电
WR1:数据锁存器写选通输入线,负脉冲有效
XFER:数据传输控制信号输入线,低电平有效
WR2:DAC寄存器写选通输入线,低电平有效
I OUT1:电流输出线,当DAC寄存器为全1时电流最大
I OUT2:电流输出线,其值与I OUT1之和为一常数
Rfb:反馈信号输入线,调整Rfb端外接电阻值可以调整转换满量程精度
Vcc:电源电压线,为+5V~+15范围
V REF:基准电压输入线,范围为:-10V~+10V
AGND:模拟地
DGND:数字地
(2)、8255A的功能简介
8255A是Intel公司生产的可编程输入输出接口芯片,它具有3个8位的并行I/O
口,具有三种工作方式,可通过程序改
变其功能,因而使用灵活,通用性强,可作为单
片机与多种外围设备连接时的中间接口电路。
8255有三种基本工作方式,三种工作方式由
工作方式控制字决定,方式控制字由CPU通过
输入/输出指令来提供.三个端口中PC口被分
为两个部分,上半部分随PA口称为A组,下半
部分随PB口称为B组.其中PA口可工作与方
式0、1和2,而PB口只能工作在方式0和1。
8255共有40个引脚,采用双列直插式封装。
各引脚功能如下:
D0--D7:三态双向数据线,与单片机数据总线连接,用来传送数据信息。
CS:片选信号线,低电平有效,表示芯片被选中。
RD:读出信号线,低电平有效,控制数据的读出。
WR:写入信号线,低电平有效,控制数据的写入。
Vcc:+5V电源。
PA0--PA7:A口输入/输出线。
PB0--PB7:B口输入/输出线。
PC0--PC7:C口输入/输出线。
RESET:复位信号线。
A1、A0:地址线,用来选择8255内部端口。
GND:地线。
8255可编程并行接口新片工作方式说明:
方式0:基本输入输出方式。
适用于三个端口的任何一个,每个端口都可以做输出或输出,输出可被锁存,输入不能锁存。
方式1:基本输入输出方式。
这是A口或B口的八位外设线用作输入或输出,C口的四条线中三条用作数据传输的联络信号和终端请求信号。
方式2:双向总线方式。
只有A口具备双向总线的方式,8位外设线用作输入或是输出,此时C口的4条线用作通讯联络信号和中断请求信号。
8255有两种控制命令字:一个是方式选择控制字,另一个是C口按位置位或复位。
(3)、键盘部分
3.硬件接线图
注:DAC 单元和8255需要不同的端口地址寻址,则在连成系统的时候,需要用不同的端口来寻址,8255用IOY0来寻址,DAC 用IOY1来寻址。
第四章 程序设计
1. 流程图
(1)、方波流程图
(2)、锯齿波流程图
开始
AL 中的数据输送到0832
AL 中的数据增量 数据00送AL 寄存器
结束
开始
将00H 送到0832端口
延时
将最大值送入0832端口
延时
结束
是最大值?
(3)、三角波流程图
开始
数据00送AL寄存器
AL中的数据输送到0832
AL中的数据自增
与上限是
否相等
AL中的数据自减
与下限00
是否相等
(4)、正弦波流程图
开始
循环次数给CX
SI指向的数据给AL
AL中的数据给0832
SI自加1指向表中下一个数据(5)、主程序流程图
开始
给变量赋初值,初始化8255
有按键按下?
判断键值
1号键开始其它键
有按键按下?1号键
2号键
产生正弦波
有按键按下?
2号键
3、4、5、6号键
改变频率或幅值
1号键
产生方波
有按键按下?3、4、5、6号键改变频率或幅值
2号键
1号键
产生三角波
3、4、5、6号键
改变频率或幅值
有按键按下?
2号键
1号键
产生锯齿波
PC有键按下有按键按下?
1号键结束有按键按下?
返回DOS
2.典型程序模块及典型编程技巧分析
在此设计中主要用了查询式的方法来确定小键盘输入,设1号键控制信号功能发生器的启动与关闭,2号键用来确定产生四种波形,由于一个键要判断四种波形故在一个循环中至少要包含四种波形都产生的情况。
3、4、5、6号键用来进行幅度增减、幅度减少、频率增加、频率减少的操作。
第一次按键的时候判断是否为1号键,是则开启仪器,进入到产生波形的程序,若为其它按键则一直等待知道出现1号键为止。
第二次按键的时候判断为1号键还是二号键,1号键则关闭仪器,2号键则产生正弦波,其它按键则一直等到1号或2号键为止。
第三次按键的要判断为1、2、3、4、5、6号键的那一个键值相应去执行相对的程序,1号键结束,二号键产生方波,3、4、5、6号键分别改变正弦波的幅值或频率,其它按键则一直等待出现这六个按键中一个并执行相应的程序为止。
第四次按键的要判断为1、2、3、4、5、6号键的那一个键值相应去执行相对的程序,1号键结束,二号键产生三角波,3、4、5、6号键分别改变方波的幅值或频率,其它按键则一直等待出现这六个按键中一个并执行相应的程序为止。
第五次按键的要判断为1、2、3、4、5、6号键的那一个键值相应去执行相对的程序,1号键结束,二号键产生锯齿波,3、4、5、6号键分别改变三角波的幅值或频率,其它按键则一直等待出现这六个按键中一个并执行相应的程序为止。
至此产生波形进行了一次循环,此时还需要第六次按键,第六次按键判断是否为1,为1则关闭仪器,为2的话继续循环产生波形。
特别值得强调的是每次按键是改变幅值和频率的则执行此操作之后还需返回到该次判断,直至按键是产生波形的产生完波形之后再继续向下执行相应的程序。
也就是说这里所说的第三次按键实际是可以产生方波的按键次数,排除了幅值频率改变的按键次数,也就是频率幅值可以改变多次之后仍然回到最初的按键判断,即频率幅值按键不会影响波形的产生。
按键之后若进行结束操作,则暂时关闭信号功能发生器,判断是否小键盘有按键按下,有按下则从新开启仪器即回到程序的开端开始运行,若没有按键按下则判断是否有PC键按下,有则返回DOS系统,若无则继续从正弦波开始通过判断按键循环产生波形。
由于频率和波形的产生不是同步的,为了知道我们改变的是何种波形的频率和幅值,我把频率和幅值的与波形的产生分开,单独改变它们,把改变后的频率和幅值的参数传递给此时产生的波形。
我设置了两个变量FLUENT和AMPLIF,用来标记改变时频率和幅值的值,同时我也设置了变量WAVESELECT,用来标记产生的是什么波形,没按一次2号键WAVESELECT自加1满4则置1,以此来循环产生四种波形。
3.课程设计中遇到的问题及解决方法
1、在课程设计中首先碰到的问题是拿到设计题目毫无思想头绪,特别是对不怎么熟悉的硬件部分更是头疼。
刚开始我想了很多,想到用8259来产生中断,还考虑到用8254来产生脉冲时钟以改变频率,虽然想到这些却无从下手,不知道怎么去实现,后面通过自己去看教科书,向老师请教,和同题目的同学交流才慢慢理清楚头绪,确定了此次课程设计的整体方案以及所要用到的芯片及所要完成的任务。
2、小键盘给定是我花了好几天的功夫才做成功的,这也是我觉得此次课程设计最难的部分和出现问题最多的部分。
开始很快就写出了小键盘给定的程序,最开始调试的时候是能进入运行的界面,可是无论怎么按键盘都没有反映,进行了死循环中,后来慢慢修改程序中的逻辑问题,小键盘的给定基本能实现,可是总是没有按照自己编写的程序来运行,本来是有PC键按下的时候应该返回到DOS 系统,可是还要按两次小键盘才能回到DOS系统,我请教了很多同学这个问题还是没有解决,最终在一位同学的帮助下花了一天的时间才把这个问题解决好。
当时我们是用Debug一步一步的运行不断的修改,不停的思考才把问题解决,最根本原因出在逻辑问题,虽然思考时逻辑很清楚,可是用汇编语言来编写时逻辑很容易混乱,因为没有采用8259A,每次判断情况是要不停地跳转,有时程序没考虑清楚就进入死循环中跳转不出来。
3、在波形的产生时,最开始我是打算建表来实现波形的产生的,一方面是有利于正弦波的产生,另一方面是考虑到程序的紧凑简介,但是用建表产生波形如果区的点太多用内存太大,取点太少则产生的波形形状不好,而且去什么样的点才能产生什么样的波形也是一个值得思考的问题。
最重要的一点是如果表中出现很大的值时如果通过加一个固定值改变频率,那么可能会出现大于0FFH的情况,是波形产生畸变。
后来我决定不建表,在程序中给个最小值和最大值,在最小值最大值之间连续取点产生波形,方波只需去最小值、最大值两点即可,三角波是从最小值一直增大到最大值再从最大值一直较少到最小值循环产生波形,锯齿波只需不断从最小值增大到最大值。
这样也方便改变幅值,我只需改变最大值即可改变幅值。
对于正弦波建表是最简单的办法。
改变频率只需改变延时。
在波形的产生过程中,我面刀的最大困难是延时的处理问题,开始的时候总是不出现波形,后面我仔细观察了示波器,不是没有出现波形,而是延时太长,因此我减少延时,波形就出来了。
在调试波形过程中我还出现一个问题是我按下键产生三角波后按键要产生锯齿波,可是按下键后没有反映而且死机了,这也是延时的问题,在产生三角波的时候延时太长,以至于计算机一直在执行产生三角波的程序无法跳转到产生锯齿波的程序中。
4、字符串输出是总是出现乱码,这是由于没有加‘$’符号
4.程序清单和程序注释
;***************根据CHECK配置信息修改下列符号值*******************
IOY0 EQU 0E400H ;片选IOY0对应的端口始地址
IOY1 EQU 0E440H ;片选IOY0对应的端口始地址
;*****************************************************************
MY8255_A EQU IOY0+00H*4 ;8255的A口地址
MY8255_B EQU IOY0+01H*4 ;8255的B口地址
MY8255_C EQU IOY0+02H*4 ;8255的C口地址
MY8255_MODE EQU IOY0+03H*4 ;8255的控制寄存器地址
DA0832 EQU IOY1+00H*4 ;DA0832的端口地址
STACK1 SEGMENT STACK
DW 256 DUP(?)
STACK1 ENDS
DA TA SEGMENT
DTABLE DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H
SINTAB DB 19H,1EH,22H,27H,2BH,2EH,31H,32H ;正弦函数表
DB 33H,32H,31H,2EH,2BH,27H,22H,1EH
DB 19H,14H,0FH,0BH,07H,04H,02H,01H
DB 00H,01H,02H,04H,07H,0BH,0FH,14H
STR1 DB 'press 1 to output wave',0AH,0DH
DB 'press 2 to quit ',0AH,0DH, 0AH,0DH,0AH,0DH,'$'
SQRTAB DB 00H,00H,00H,00H,00H,00H,00H,00H
DB 00H,00H,00H,00H,00H,00H,00H,00H
DB 13H,13H,13H,13H,13H,13H,13H,13H
DB 13H,13H,13H,13H,13H,13H,13H,13H
STR2 DB 'press 1 to sin wave ',0AH,0DH
DB 'press 2 to recangle ',0AH,0DH
DB 'press 3 to square ',0AH,0DH
DB 'press 4 to triangle ',0AH,0DH
DB 'press 5 to return0 ',0AH,0DH ,0AH,0DH,0AH,0DH, '$'
STR3 DB 'press 1 to reduce fecency ',0AH,0DH
DB 'press 2 to increase fecency ',0AH,0DH
DB 'press 3 to reduce amplitude ',0AH,0DH
DB 'press 4 to increase amplitude',0AH,0DH
DB 'press 5 to return0 ',0AH,0DH ,0AH,0DH,0AH,0DH, '$'
SQU DB 'output squre wave now .......',0AH,0DH, 0AH,0DH, '$'
TRI DB 'output triangle wave now .......',0AH,0DH, 0AH,0DH, '$'
REC DB 'output recangle wave now .......',0AH,0DH, 0AH,0DH, '$'
SIN DB 'output sin wave now .......',0AH,0DH, 0AH,0DH, '$'
AMPL DB 3
FENC DB 3
TIAOFU DB ?
TIAOPIN DB ?
SQUARE DB ?
KEYASS DB ?
DA TA ENDS ;键值表,0~F对应的7段数码管的段位值
CODE SEGMENT
ASSUME CS:CODE,DS:DA TA
START: MOV AX,DA TA
MOV DS,AX
MOV SI,3000H ;建立缓冲区,存放要显示的键值
MOV AL,00H ;先初始化键值为0
MOV [SI],AL
MOV [SI+1],AL
MOV [SI+2],AL
MOV [SI+3],AL
MOV DI,3003H
MOV DX,MY8255_MODE ;初始化8255工作方式
MOV AL,81H ;方式0,A口、B口输出,C口低4位输入
OUT DX,AL
PREBEGIN:
MOV AH,09H ; 显示第一个菜单
MOV DX,OFFSET STR1
INT 21H
MOV SI,3000H ; 把数码管清0
MOV AL,00H ; 先初始化键值为0
MOV [SI],AL
MOV [SI+2],AL
MOV [SI+3],AL
MOV DI,3003H
BEGIN: CALL DIS ;显示刷新
CALL GETKEY1 ;在第一菜单下,等待按键的按下
MOV SI,OFFSET KEYASS
MOV AL,[SI]
CMP AL,1 ;按下第二个键就退出
JZ QUIT
CMP AL,0 ;按下第一个键进入第二个菜单
JZ LBEGIN
JMP BEGIN ;不是按下第一或二键就继续等待输入
LBEGIN:
MOV AH,09H ;显示第二个标题
MOV DX,OFFSET STR2
INT 21H
LBEGIN4: CALL GETKEY1 ;第二个菜单等待输入
MOV SI,OFFSET KEYASS
MOV AL,[SI]
CMP AL,4 ;第5个键退出
JZ LBEGIN1
CMP AL,0 ;第一个键到sin(正弦)函数
JZ LBEGIN6
CMP AL,1 ;第二个键到rec(锯齿)函数
JZ LBEGIN7
CMP AL,2 ;第三个键到squ(方波)函数
JZ LBEGIN2
CMP AL,3 ;第四个键到tri(三角波)函数
JMP LBEGIN3 ; 其他键则跳到继续等待输入
LBEGIN2: CALL SQUREW
JMP PREBEGIN
LBEGIN5: CALL TRIANW
JMP PREBEGIN
LBEGIN6: CALL SINW
JMP PREBEGIN
LBEGIN7: CALL RECW
JMP PREBEGIN ;执行完输出波形之后回到第一个菜单LBEGIN3: JMP LBEGIN4
LBEGIN1:
MOV AH,1 ;判断PC键盘是否有按键按下
INT 16H
JZ PREBEGIN
QUIT: MOV AX,4C00H ;返回到DOS
INT 21H
;上面是主程序
TRIANW PROC NEAR ;三角波的子程序
MOV AH,09H
MOV DX,OFFSET TRI
INT 21H
MOV AH,09H
MOV DX,OFFSET STR3
INT 21H ;..............
MOV AL,FENC ;初始化显示管的值为3
MOV SI,3000H
MOV AL,AMPL
MOV SI,3001H
MOV [SI],AL
TRIAN1: CALL AMPLFENC
MOV SI,OFFSET KEYASS
MOV AL,4
CMP [SI],AL
JZ TRIAN4
CALL DIS
TRILOOP11: ;输出三角波
MOV SI,3000H ;幅值
MOV BL,[SI]
MOV SI,OFFSET TIAOFU
MOV [SI],BL
MOV SI,3001H
MOV BL,[SI]
MOV SI,OFFSET TIAOPIN
MOV [SI],BL
TRILOOP: MOV AL,00H ;D/A转换起始值
TRIUP: PUSH AX
MOV BL,TIAOFU
MUL BL
MOV DX,DA0832 ;启动D/A转换
OUT DX,AL
POP AX
MOV CL,TIAOPIN
MOV CH,00H
DALLYTRI1:
CALL DALLY
CALL DIS
CALL CCSCAN
JNZ TRIAN1
LOOP DALLYTRI1
INC AL
CMP AL,33H
JNE TRIUP
TRIDOWN: PUSH AX
MOV BL,TIAOFU
MUL BL
MOV DX,DA0832
OUT DX,AL
POP AX
MOV CL,TIAOPIN
MOV CH,00H
DALLYTRI2:
CALL DALLY
CALL DIS
CALL CCSCAN
JNZ TRIAN1
LOOP DALLYTRI2
DEC AL
CMP AL,00H
JNE TRIDOWN
JZ TRILOOP ;无按键则跳回继续循环,有则退出
TRIAN4:
RET
TRIANW ENDP
RECW PROC NEAR ;锯齿波的子程序
MOV AH,09H
MOV DX,OFFSET REC
INT 21H
MOV AH,09H
MOV DX,OFFSET STR3
INT 21H
MOV DI,OFFSET FENC ;初始化显示管的值为5
MOV AL,[DI]
MOV SI,3000H
MOV [SI],AL
MOV DI,OFFSET AMPL
MOV AL,[DI]
MOV SI,3001H
MOV [SI],AL
REC1:
CALL AMPLFENC
MOV SI,OFFSET KEYASS
MOV AL,4
CMP [SI],AL
JZ REC4
CALL DIS
MOV SI,3000H ;幅值
MOV BL,[SI]
MOV SI,OFFSET TIAOFU
MOV [SI],BL
MOV SI,3001H
MOV BL,[SI]
MOV SI,OFFSET TIAOPIN
MOV [SI],BL
RECLOOP11:
MOV AL,00H ;D/A转换起始值
RECUP: PUSH AX
MOV BL,TIAOFU
MUL BL
MOV DX,DA0832 ;启动D/A转换
OUT DX,AL
POP AX
MOV SI,OFFSET TIAOPIN
MOV CL,[SI]
MOV CH,00H
DALLYREC1:
CALL DALLY
CALL DIS
CALL CCSCAN
JNZ REC1
LOOP DALLYREC1
INC AL
CMP AL,33H
JNE RECUP
JZ RECLOOP11 ;无按键则跳回继续循环,有则退出REC4:
RET
RECW ENDP
SINW PROC NEAR ;正弦波的子程序
MOV AH,09H
MOV DX,OFFSET SIN
INT 21H
MOV AH,09H
MOV DX,OFFSET STR3
INT 21H
MOV DI,OFFSET FENC
MOV AL,[DI]
MOV SI,3000H
MOV [SI],AL
MOV DI,OFFSET AMPL
MOV AL,[DI]
MOV SI,3001H
MOV [SI],AL
SINA1:
CALL AMPLFENC
MOV SI,OFFSET KEYASS
MOV AL,4
CMP [SI],AL
JZ SINA4
CALL DIS
MOV SI,3000H
MOV BL,[SI]
MOV DI,OFFSET TIAOFU
MOV [DI],BL
MOV SI,3001H
MOV AL,[SI]
MOV SI,OFFSET TIAOPIN
MOV [SI],AL
SINLOOP1:
MOV SI,OFFSET SINTAB SINLOOP2:
MOV AL,[SI]
MOV BL,TIAOFU
MUL BL
MOV DX,DA0832 ;启动D/A转换
OUT DX,AL
;push dx
PUSH AX
PUSH SI
PUSH CX
MOV CL,TIAOPIN
MOV CH,00H
DALLYSIN1:
CALL DALLY2
CALL DIS
CALL CCSCAN
JNZ SINA1
LOOP DALLYSIN1
POP CX
POP SI
POP AX
;pop dx
INC SI
CMP SI,OFFSET STR1
JNZ SINLOOP2
JMP SINLOOP1
SINA4:
RET
SINW ENDP
SQUREW PROC NEAR ;方波发生子程序
MOV AH,09H ;显示当前正在输出正弦波
MOV DX,OFFSET SQU
INT 21H
MOV AH,09H ;第三个菜单
MOV DX,OFFSET STR3
INT 21H
MOV DI,OFFSET FENC ;初始化显示管的值为5
MOV AL,[DI]
MOV SI,3000H
MOV [SI],AL
MOV DI,OFFSET AMPL
MOV AL,[DI]
MOV SI,3001H
MOV [SI],AL
SQUR1:
CALL AMPLFENC ;调节幅值频率子程序
;有键按下是调节幅值平率
MOV SI,OFFSET KEYASS ;按下第五个键就退出
MOV AL,4
CMP [SI],AL
JZ TRI4
CALL DIS
MOV SI,3000H
MOV BL,[SI]
MOV DI,OFFSET TIAOFU
MOV [DI],BL
MOV SI,3001H
MOV AL,[SI]
MOV SI,OFFSET TIAOPIN
MOV [SI],AL
TRILOOP1: ;输出方波形
MOV DX,DA0832 ;输出低电平
MOV AL,00H
OUT DX,AL
CALL DIS ;刷新
CALL DALLY1 ;延时
CALL CCSCAN ;再次扫描按键
JNZ SQUR1 ;有键按下则跳置squr1,改变幅值频率
MOV BL,TIAOFU
MOV AL,33H
MUL BL
MOV DX,DA0832 ;输出高电平
OUT DX,AL
CALL DIS ;刷新
CALL DALLY1 ;延时
CALL CCSCAN ;再次扫描按键
JNZ SQUR1 ;有键按下则跳置tri1
JZ TRILOOP1 ;没按键时继续输出波形
TRI4: ;退出
RET
SQUREW ENDP
AMPLFENC PROC NEAR ;调节幅值频率子程序
TRI3: CALL DIS ;刷新
CALL CCSCAN ;再次扫描按键
JNZ TRI1 ;有键按下则跳置tri1
JMP TRI2 ;没按键按下就跳出该子程序
TRI1:
CALL DIS ;刷新
CALL GETKEY1
MOV SI,OFFSET KEYASS
MOV AL,[SI]
CMP AL,4 ;第五个键就退出
JZ TRI2
CMP AL,0 ;第一个键减少频率
JNZ TRI5
MOV DI,3001H
MOV BL,[DI]
CMP BL,01H
JE TRI2
DEC BL
MOV [DI],BL
JMP TRI2
TRI5: CMP AL,1 ;第二个键增加频率
JNZ TRI6
MOV DI,3001H
MOV BL,[DI]
CMP BL,05H
JE TRI2
INC BL
MOV [DI],BL
JMP TRI2
TRI6: CMP AL,2 ;第三个键减少幅度
JNZ TRI7
MOV DI,3000H
MOV BL,[DI]
CMP BL,01H
JE TRI2
DEC BL
MOV [DI],BL
JMP TRI2
TRI7: CMP AL,3 ;第三个键增加幅度
JNZ TRI2
MOV DI,3000H
MOV BL,[DI]
CMP BL,05H
JE TRI2
INC BL
MOV [DI],BL
TRI2:
RET
AMPLFENC ENDP
GETKEY1 PROC NEAR ;等待按键输入,输入的按键值送到keyass
GETKEY11: CALL DIS ;显示刷新
CALL DALLY
CALL DALLY
; CALL CLEAR ;清屏
CALL CCSCAN ;再次扫描按键
JNZ GETKEY2 ;有键按下则跳置GETKEY2
JMP GETKEY11 ;否则跳回开始继续循环
GETKEY2: MOV CH,0FEH
MOV CL,00H ;设置当前检测的是第几列
COLUM: MOV AL,CH ;选取一列,将X1~X4中一个置0 MOV DX,MY8255_A
OUT DX,AL
MOV DX,MY8255_C ;读Y1~Y4,用于判断是哪一行按键闭合
IN AL,DX
L1: TEST AL,01H ;是否为第1行
JNZ L2 ;不是则继续判断
MOV AL,00H ;设置第1行第1列的对应的键值
JMP KCODE
L2: TEST AL,02H ;是否为第2行
JNZ L3 ;不是则继续判断
MOV AL,04H ;设置第2行第1列的对应的键值
JMP KCODE
L3: TEST AL,04H ;是否为第3行
JNZ L4 ; 不是则继续判断
MOV AL,08H ;设置第3行第1列的对应的键值
JMP KCODE
L4: TEST AL,08H ;是否为第4行
JNZ NEXT ;不是则继续判断
MOV AL,0CH ;设置第4行第1列的对应的键值
KCODE: ADD AL,CL;将第1列的值加上当前列数,确定按键值;CALL PUTBUF ;保存按键值
PUSH SI
MOV SI,OFFSET KEYASS
MOV [SI],AL
POP SI
PUSH AX
KON: CALL DIS ;显示刷新
;CALL CLEAR ;清屏
CALL CCSCAN ;扫描按键,判断按键是否弹起
JNZ KON ;未弹起则继续循环等待弹起
POP AX
JMP KERR
NEXT: INC CL;当前检测的列数递增
MOV AL,CH
TEST AL,08H ;检测是否扫描到第4列
JZ KERR ;是则跳回到开始处
RO L AL,1 ;没检测到第4列则准备检测下一列
MOV CH,AL
JMP COLUM
KERR:
GETKEY1 ENDP
CLEAR PROC NEAR ;清除数码管显示子程序MOV DX,MY8255_B ;段位置0即可清除数码管显示
MOV AL,00H
OUT DX,AL
RET
CLEAR ENDP
DALLY1 PROC NEAR ;软件延时子程序
PUSH CX
PUSH AX
MOV CH,TIAOPIN
MOV CL,0FFH
D11: MOV AX,00FFH
D21: DEC AX
PUSH AX
PUSH CX
CALL DIS
;CALL CCSCAN ;再次扫描按键
;JNZ yquit ;有键按下则跳置tri1
POP CX
POP AX
JNZ D21
LOOP D11
POP AX
POP CX
YQUIT:
RET
DALLY1 ENDP
CCSCAN PROC NEAR ;扫描是否有按键闭合子程序
PUSH AX
MOV AL,00H
MOV DX,MY8255_A ;将4列全选通,X1~X4置0
OUT DX,AL
MOV DX,MY8255_C
IN AL,DX ;读Y1~Y4
NOT AL
AND AL,0FH ;取出Y1~Y4的反值
POP AX
RET
CCSCAN ENDP
DIS PROC NEAR ;显示键值子程序
PUSH AX ;以缓冲区存放的键值为键值表偏移找到键值并显示
MOV SI,3000H
MOV DL,0F7H
MOV AL,DL
AGAIN: PUSH DX
MOV DX,MY8255_A
OUT DX,AL ;设置X1~X4,选通一个数码管
MOV AL,[SI] ;取出缓冲区中存放键值
MOV BX,OFFSET DTABLE
AND AX,00FFH
ADD BX,AX
MOV AL,[BX] ;将键值作为偏移和键值基地址相加得到相应的键值
MOV DX,MY8255_B
OUT DX,AL ;写入数码管A~Dp
CALL DALLY
INC SI ;取下一个键值
POP DX
MOV AL,DL
TEST AL,01H ;判断是否显示完?
JZ OUT1 ;显示完,返回
ROR AL,1
MOV DL,AL
JMP AGAIN ;未显示完,跳回继续
OUT1: POP AX
RET
DIS ENDP
PUTBUF PROC NEAR ;保存键值子程序
MOV SI,DI
MOV [SI],AL
DEC DI
CMP DI,2FFFH
JNZ GOBACK
MOV DI,3003H
GOBACK: RET
PUTBUF ENDP
DALLY2 PROC NEAR ;软件延时子程序。