当前位置:文档之家› 汇编语言课程设计 电子闹钟

汇编语言课程设计 电子闹钟

电子闹钟

一、课题内容和要求

题目描述:利用汇编语言实现一个可以在显示器上显示时、分、秒的电子时钟,并能提供整点报时功能。

基本要求:(1)设计一个基本的具有显示时、分、秒的电子时钟。

(2)到整点或预定的报警时间,能够以不同的音乐进行报时,可以自行设置闹钟报警时间;

(3)实物演示时要求讲出程序原理和设计思想;

(4)程序运行良好、界面清晰。

提高要求:设计一个具有钟面、分针、秒针的指针式钟表,在圆盘上有均匀分布的60根刻度,对应小时的刻度用不同颜色的长刻度区别,并且将12、3、6、9对应的拉丁文绘制于表盘外。

设计提示:(1)指针式钟表的绘制。将屏幕设置成图形显示方式,通过画点、画线,画圆等基本程序完成钟表的绘制。表盘圆周上刻度线段两端点坐标计算是钟表绘制的核心部分。

(2)秒针、分针、时针的转动。是经过一定的延时时间,通过在下一位置重新画一个,在原来的位置用背景色覆盖的方法实现。

(3)音乐的演奏。利用CPU支持的外围电路8254与8255,通过汇编程序改变8255的PB0,PB1口,接通扬声器,使得计算机能够发出一定频率的声音,同时通过8254的与8255连接的2号计数器控制指定频率,从而达到控制扬声器的音乐的效果。通过建立适当的延时程序达到一定时间后则改变2号计数器产生的方波的频率,实现音乐程序的演奏。

二、需求和思路分析

经分析本次程序设计的主要内容主要分为如下的几个模块:

当前时间的获取并显示,码制转换,设定闹钟报鸣的时间,不同频率的闹铃声,钟表的绘制和并实现动态等模块。其中钟表的绘制和动态走动部分比较难是本次课程设计的提高部分,且改模块可单独形成一个模块,所以放到最后进行考虑

1时间的获取可以用INT 21H的2CH功能,该功能调用DOS时间调用功能,功能号:2CH,小时,分钟,秒数分别保存在,保存的形式是以二进制的形式,故显示时要

2码制转化利用ASCII码与二进制码的关系ASCII=二进制+30H

3闹钟鸣叫主要利用8254的二号计数器和8255的PB0和PB1来设定

4 闹钟的表盘,指针的绘制,并实现时针,分针,秒针的走动。主要通过过图形的画点进行操作,并通过在固定的区域内不断的刷屏来实现。

三、概要设计

(一)算法设计及重要程序流程图

1)程序整体流程

2)edittime子程序流程图

2)editmusic子程序

3)打开和关闭扬声器

此处重要用到了8254和8255的相关知识,书中P238有相关代码

首先,应该读出8255的PB端口当前的状态,将PB0和PB1分别置1,以读修改写的方式修改PB0和PB1接通扬声器。

其次,利用8254的2号计数器产生XXX Hz 的方波,此处计数初值利用公式 N=fclk1 /fout2

对8254先写低8位,再写高8位,out2输出方波

最后,将8255的PB0和PB1回复位00,用AND AL,11111100B来修改

4)BCTD子程序的流程图

该子程序程序功能主要是实现二进制转化成相应BCD码

AX输入参数

AX输出参数,存放调整过的BCD码

(二)变量名声明

DATA SEGMENT

MESS1 DB ' ****************ASM ASSIGNMENT**************** ',0AH,0DH

DB ' ',0AH,0DH

DB ' ***************ELECTRONIC CLOCK*************** ',0AH,0DH

DB ' ',0AH,0DH

DB ' ',0AH,0DH

DB ' *******PRESS C OR C TO EDIT THE ALARM TIME PRESS M OR M TO CHANGE SOUND!**** ',0AH,0DH

DB ' ',0AH,0DH

DB ' ***********PRESS ESC BUTTON TO EXIT*********** ',0AH,0DH,'$'

TN DB 'PLEASE INPUT THE NEW TIME (HH:MM:SS):',0DH,0AH,'$'

MUSICMESS DB 'PLEASE CHOOSE THE TYPE OF MUSIC:1(FAST) 2(MIDDLE)

3(SLOW)',0DH,0AH,'$'

MESS2 DB '*******TIME IS:',0AH,0DH,'$'

T_BUFF DB 40 ;在数据段开一段时间显示缓冲区

DB ?

DB 40 DUP (?)

TEMPHOR DB ? ;存放键入的定时时间的小时

TEMPMIN DB ? ;存放键入的定时时间的分钟

TEMPSEC DB ? ;存放键入的定时时间的秒数

MUSIC DW 800 ;存放默认音乐的频率数

DATA ENDS

STACK SEGMENT

DB 100 DUP(?)

STACK ENDS

四、详细设计

课题任务实现的源程序(可以是一组源程序,每个功能模块采用不同的函数实现),源程序要按照写程序的规则来编写。要结构清晰,重点函数的重点变量,重点功能部分要加上清晰的程序注释。

(一)

1主函数代码

CODE SEGMENT

ASSUME CS:CODE,SS:ST ACK,DS:DATA ;确定各个逻辑段的类型

START:

MOV AX,DATA

MOV DS,AX

CALL CLEAR ;调用清屏子程序

DISPLAY: ;时间显示部分

MOV AX,DATA

MOV DS,AX

MOV BX,OFFSET T_BUFF ;送T_BUFF的偏移地址到BX

MOV AH,2CH ;调用DOS时间调用功能,功能号:2CH,小时,分钟,秒数分别保存在CH,CL,DH中INT 21H ;判断时间是否相等

SUB DH,1 ;秒钟+1修正

CALL CHECK

MOV AL,CH ;小时数设定

MOV AH,0

CALL BCTD ;调用进制转换子程序二进制转BCD码子程序

PUSH AX

AND AL,0F0H ;选取AL高四位

MOV CL,4 ;设置右循环的次数

ROL AL,CL ;右循环

OR AL,30H ;加30H得到ACSII码

MOV [BX],AL ;将得到的结果送到T_BUFF缓冲区

INC BX ;BX自加1,指针指向下一个缓冲区的下一个地址

POP AX

AND AL,0FH ;选取低四位

OR AL,30H

MOV [BX],AL ;将转换后的低四位值送入缓冲区的第二个地址INC BX

;----------------------------------------------------------

MOV AL,':' ;显示分隔符号

MOV [BX],AL

INC BX

;-------------------------------------------------------

MOV AH,2CH

INT 21H

MOV AL,CL ;分钟数设定

MOV AH,0

CALL BCTD

PUSH AX

AND AL,0F0H

MOV CL,4

ROL AL,CL

OR AL,30H

MOV [BX],AL

INC BX

POP AX

AND AL,0FH

OR AL,30H

MOV [BX],AL

INC BX

;------------------------------------------------------------------------- MOV AL,':' ;显示分隔符号

MOV [BX],AL

INC BX

;------------------------------------------------------------------------- MOV AH,2CH ;秒设定

INT 21H

MOV AL,DH

MOV AH,0

CALL BCTD

PUSH AX

AND AL,0F0H

MOV CL,4

ROL AL,CL

OR AL,30H

MOV [BX],AL

INC BX

POP AX

AND AL,0FH

OR AL,30H

MOV [BX],AL

INC BX

;----------------------------------------------------------------------

MOV AL,'$' ;将字符串的结束位送至显示缓冲区的最后一位

MOV [BX],AL

;------------------------------------------------------------------------

PUSH BX ;置光标位置,AH=2,BH=0,DH跟DL分别为行号与列号,并入栈保护BX MOV AH,2 ;0~1用于此程序快下边的在下面的两个置光标位置

MOV BH,0

MOV DH,17

MOV DL,41

INT 10H

POP BX

LEA DX,T_BUFF ;送T_BUFF偏移地址到DX,并调用DOS显示功能,功能号为9 MOV AH,9

INT 21H ;至此当前事前时间的显示功能结束!

PUSH BX ;置光标位置

MOV AH,2

MOV BH,0

MOV DH,0

MOV DL,0

INT 10H

POP BX

LEA DX,MESS1

MOV AH,9

INT 21H ; 显示MESS1

PUSH BX ;置光标位置

MOV AH,2

MOV BH,0

MOV DH,17

MOV DL,21

INT 10H

POP BX

LEA DX,MESS2

MOV AH,9

INT 21H ; 显示MESS2

;-----------------------------

CALL DELAY1

MOV AH,1 ;调用键盘I/O中断功能号1,获取键值到AL INT 16H

CMP AL,'C' ;是C键,转到时间修改程序

JE EDITTIME

CMP AL,'C' ;是C键,转到时间修改程序

JE EDITTIME

CMP AL,'M';是M键,转到闹铃种类设定程序

JE EDITMUSIC

CMP AL,'M' ;是M键,转到闹铃种类设定程序

JE EDITMUSIC

CMP AL,1BH

JZ QUIT ;是ESC键,退出程序

JMP DISPLAY

QUIT:

MOV AH,4CH ;程序终止功能号

INT 21H

RET

2功能函数代码

1)二进制转BCD码子程序

BCTD PROC NEAR ;二进制转BCD码子程序

;AX输入参数

;AX输出参数,存放调整过的BCD码

MOV DX,AX

MOV AX,0

MOV CX,16 ;设循环次数

BCTD1:

CLC ;清进位标志C

RCL DX,1 ;通过进位的循环右移

ADC AL,AL ;带进位加法

DAA ;加法的十进制调整

XCHG AL,AH ;交换高、低八位

ADC AL,AL

DAA

XCHG AL,AH

LOOP BCTD1 ;循环次数保存在CX里

RET

BCTD ENDP

2)清屏CLEAR子程序

CLEAR PROC NEAR

PUSH AX ;入栈保护现场

PUSH BX

PUSH CX

PUSH DX

MOV AX,0600H ;AH=06(滚动)AL=00(全屏空白) MOV BH,3EH ;设置背景颜色(2)和前景颜色(E) SUB CX,CX

MOV DX,5F5FH

INT 10H

POP DX ;出栈恢复现场

POP CX

POP BX

POP AX

RET

CLEAR ENDP

3)精确延迟时间子程序delay1

DELAY1 PROC ;精确延迟时间子程序

MOV DX,04FFH ;循环次数

UP: XOR CX,CX

A: NOP

LOOP A

DEC DX

JNZ UP

RET

DELAY1 ENDP

4)设定定时时钟EDITTIME子程序

EDITTIME PROC ;时间修改子程序

PUSH AX ;入栈保护数据

PUSH BX

PUSH CX

PUSH DX

PUSHF

MOV DX,OFFSET TN ;显示修改时间的格式提示

MOV AH,09H

INT 21H

MOV DX,OFFSET T_BUFF ;数据缓冲区的数据输入

MOV AH,0AH

INT 21H

AND DX,0H

LEA BX,T_BUFF INC BX

INC BX

INC BX

MOV DH,[BX]

SUB DH,30H

INC BX

MOV DL,[BX]

SUB DL,30H

MOV CL,10

MOV AL,DH

MUL CL

ADD AL,DL

MOV CH,AL

MOV TEMPHOR,AL

INC BX

INC BX

MOV DH,[BX]

SUB DH,30H

INC BX

MOV DL,[BX]

SUB DL,30H

MOV CL,10

MOV AL,DH

MUL CL

ADD AL,DL

MOV CL,AL

MOV TEMPMIN,AL

INC BX

INC BX

MOV DH,[BX]

SUB DH,30H

INC BX

MOV DL,[BX]

SUB DL,30H

MOV CL,10

MOV AL,DH

MUL CL

ADD AL,DL

MOV DH,AL

MOV TEMPSEC,AL

POPF ;出栈恢复数据

POP DX

POP CX

POP BX

POP AX

JMP START

RET

EDITTIME ENDP

5)检验定时时间是否到CHECK子程序

CHECK PROC

PUSH AX

PUSH BX

CMP CH,TEMPHOR ;设置定点报时JNE CF

CMP CL,TEMPMIN

JNE CF

CMP DH,TEMPSEC

JNE XIANG

CF1

CMP CL,0 ;设置整点报时JNE CF

CMP DH,0

JNE CF

XIANG:

CALL OPEN ;打开扬声器

PUSH DX

PUSH CX

MOV DX,12H

MOV AX,34DEH

MOV CX,MUSIC

DIV CX

OUT 42H,AL

MOV AL,AH

OUT 42H,AL

MOV AH,1

INT 21H

POP CX

POP DX

CALL CLOSE ;关闭扬声器CF:

POP BX

POP AX

RET

CHECK ENDP

6)开启和关闭扬声器子程序open和close

OPEN PROC

PUSH AX

IN AL,61H

OR AL,03H

OUT 61H,AL

POP AX

RET

OPEN ENDP

CLOSE PROC

PUSH AX

IN AL,61H

AND AL,0FCH

OUT 61H,AL

POP AX

RET

CLOSE ENDP

6)设置闹钟音乐种类子程序editmusic

EDITMUSIC PROC

PUSH AX ;入栈保护数据

PUSH BX

PUSH CX

PUSH DX

PUSHF

MOV DX,OFFSET MUSICMESS ;显示修改音乐的种类提示

MOV AH,09H

INT 21H

MOV DX,OFFSET T_BUFF ;数据缓冲区的数据输入

MOV AH,0AH

INT 21H

AND DX,0H

LEA BX,T_BUFF

INC BX

INC BX

INC BX

MOV AL,[BX]

CMP AL,'1'

JE M800TO

CMP AL,'2'

JE M1600TO

CMP AL,'3'

JE M3200TO

M800TO: MOV MUSIC,800

JMP T

M1600TO: MOV MUSIC,1600

JMP T

M3200TO: MOV MUSIC,3200

T:

POPF ;出栈恢复数据

POP DX

POP CX

POP BX

POP AX

JMP START

RET

EDITMUSIC ENDP

五、测试数据及其结果分析

1)运行画面

2)测试结果

A)键入c或C

会出现提示“PLEASE INPUT THE NEW TIME (HH:MM:SS):”

再输入19:08:40。

回车结束后,在19:08:40时,闹钟会鸣叫。

B)键入m或M

会出现提示“PLEASE CHOOSE THE TYPE OF MUSIC:1(FAST) 2(MIDDLE) 3(SLOW):”

回车后会设定此时的闹铃鸣叫的频率

六、调试过程中的问题

本次程序设计中遇到了很多的问题,在设计每一个模块都有遇到了一定的难度。

首先关于,如何获得系统当前的时间,查阅了INT 21H,21H的2CH可以返回的的CH,CL,DH中分别为时,分,秒但是都是二进制的,故需要的进行二进制的码制,写代码时发现通过寄存器移位的可以十分的节省寄存器的使用数目。

其次在写EDITTIME的子程序是发生了一个错误,很久才改正。我在使用21H的0AH向T_BUFFER内存空间输入字符串是,第一个位置是初始化时设定

的T_BUFFER的最大长度,第二个位置是实际输入的长度,我于是INC BX两次(BX发的T_BUFFER的地址),以为能够得到我的输入的第一个字符,但是结果是错误的,查了了很久才发现,其实我在调用该子程序前的一个控制已经输入了一个字符,该字符已经存入了T_BUFFER,故此处应该在INC BX。

在EDITMUSIC的子程序中同样会遇到类似问题。

在编写程序中由于经常的要使用寄存器,有时没有将其压栈保存,导致寄存器的值发生了不可知的变化。所以一定要注意压栈的使用

在实验中使用MASM开发环境,因为开始发现未来汇编的JNE等功能的转移范围有限制,但是在MASM中转移的范围很大。

本程序并没有对一些异常输入和其他的异常进行处理,所以在程序的健壮性上有所欠缺。后来一直在看关于绘制钟表的相关代码,看懂了一半,但是还是没能完成,希望以后有机会能够完成

七、专业课程设计总结

通过本次的课程设计,对汇编语言和微型计算机接口计数,有了更加深刻认识,复习了关于8254和8255的相关知识。自己设计了程序的全部的流程,对每个环节都要十分清楚。代码完成后深切的感觉到,编写代码前的设计十分的重要。因为,如果等到完成了许多功能后,再需要增添一个功能,或改写一个光标的位置,汇编语言的改写比JA VA等高级语言麻烦的多,十分不好改,毕竟汇编是一种低级语言,没有面向对象的概念,很有可能大部分带都重写,导致效率十分低。在程序的调试过程中熟悉了通过观察各个寄存器内值的变化来跟踪程序的运行是否有误。

在编写程序的时候发现许多的技巧比如要学会多利用左移或右移的操作,这样会十分的节省寄存器的使用。另外当你的寄存器不够时,可以先把几个寄存器压栈,进行操作后在弹出栈,这样可以解决寄存器不够,或某些寄存器的值不知觉的被改变。

总之这次的汇编实验比JA VA那部分要难一点,还好最后把基本功能完成了,能够实现一个电子闹钟的定时,整点鸣叫,设定闹钟铃声的种类。自己第一次编写这么多的汇编的代码。唯一有点遗憾的地方是,提高的钟表指针走动的功能没能够实现,网上找到一个范例,但是只看懂了一半,只看懂了绘制的过程,对指

针如何走动还是没弄懂,希望以后有机会,能够对无论是汇编的图形绘制还是其他高级语言的图形绘制再次实践一下。充分的锻炼自己!

相关主题
文本预览
相关文档 最新文档