合肥工业大学微机原理课程设计数字闹钟讲解.docx
《合肥工业大学微机原理课程设计数字闹钟讲解.docx》由会员分享,可在线阅读,更多相关《合肥工业大学微机原理课程设计数字闹钟讲解.docx(26页珍藏版)》请在冰点文库上搜索。
![合肥工业大学微机原理课程设计数字闹钟讲解.docx](https://file1.bingdoc.com/fileroot1/2023-6/11/af26636a-1120-4f8f-b648-861de763e0c9/af26636a-1120-4f8f-b648-861de763e0c91.gif)
合肥工业大学微机原理课程设计数字闹钟讲解
合肥工业大学
计算机与信息学院
课程设计
课程:
微机原理与接口技术设计
专业班级:
计算机科学与技术13-1班
学号:
2013211601
姓名:
康安
一、
设计题目及要求:
1.通过8253定时器产生1秒脉冲定时中断。
在中断服务程序中实现秒、分、小时的进位(24
小时制)。
2.在七段数码管上显示当前的时分秒(例如,12点10分40秒显示为121040)。
3.按“C”键可设置时钟的时间当前值(对准时间)。
4.按“D”键设置闹铃时间。
5.按“E”键表示时钟开始运行。
6.程序运行时,首先按“D”键设置闹铃时间,然后按“C”键设置时钟的时间,再按“E”
让时钟开始运行。
当前时间运行到闹铃时间时,6个数码管全部闪烁显示“8”。
二、设计思想:
总体思想:
1、功能概述:
实验箱连线:
本实验建立在Dais实验箱基础上完成的基本连线及程序如下:
138译码器:
A,B,C,D,分别连接A2,A3,A4,GS;
y0连接8253的CS片选信号;
y1连接8259的CS片选信号;
8253连线:
分频信号T2接8253的CLK0;
8253的OUT0接8259的IR7;
8253的gate信号接+5V;
8259连线:
8259的数据线接入数据总线;
本程序包括显示模块,键盘扫描模块,时间计数模块,设置模块等几个模块,
(1)程序运行后,LED显示000000初始值,并且开始计数
(2)按C键设置初始时间,LED清零,显示待输入状态“-------”,之后用户输入数字,更改LED显示内容。
考虑到第一个数只能是0,1,2,当第一个数显示2时第二个数只能显示0~4,同理下面各位应满足时钟数值的合理的取值;
(3)按D键设置闹钟时间,清除LED显示内容,显示待输入状态“------”,之后用户输入数字,更改LED显示内容。
数字的取值情况和按C键设置初始时间相同。
(4)按E键运行时钟,LED显示内容恢复为按C键设置的时间,并开始计时。
(5)当LED显示的数字和预先设置好的闹钟相同时,更改LED显示状态,改为“888888”,闪烁显示10秒后恢复原来的时间,继续计数。
2、主程序设计(他人完成)
主程序中完成通过调用子程序完成对8253及8259的初始化,对8259进行中断设置。
主要在显示子程序和键盘子处理程序之间不断循环,8253每一秒给8259一个刺激,当8259接受到刺激后会给CPU一个中断请求,CPU会转去执行中断子程序,而中断子程序设置成时间计数加,即完成电子表的整体设计。
当LED显示的时间达到预先设置的时间,关闭中断,更改显示内容,在显示一段时间后恢复显示,打开中断,使电子表恢复运行。
3、LED显示子程序设计(他人完成)
本程序显示部分用了6个共阳极LED作为显示管,显示程序要做到每送一次段码就送一次位码,每送一次位码后,将位码中的0右移1位作为下次的位码,从而可以实现从左到右使6个LED依次显示出相应的数字。
虽然CPU每隔一定时间便执行显示程序,但只要这个时间段不太长,由于人眼的视觉作用,就可以在6个LED上同时见到数字显示。
4、键盘扫描子程序设计(他人完成)
本程序主要实现对键盘的按键进行扫描,判断用户是否按下的键值,并将按下的键值作为参数返回。
5、时钟功能设置(独立负责)
本程序段负责实现判断用户按下的键值,根据按下的键值转入不同的程序段执行相应的功能设置。
判断键值的方法为设置三个标志位,三个标志位分别对应3个按键,当按键被按下时,将对应的标志位置为1,在程序段中对三个标志位进行判断,从而实现不同的功能设置。
首先调用键盘扫描子程序GetKey获取用户输入的键值,之后将键值分别与0ch,0dh,0eh比较:
若键值为C,则跳入下一个程序段SETC,将对应的标志位ButtonC置为1,其余两个标志ButtonD和ButtonE为0;
若键值为D,则跳入下一个程序段SETD,将对应的标志位ButtonD置为1,其余两个标志ButtonC和ButtonE为0;
若键值为E,则跳入下一个程序段SETE,将对应的标志位ButtonE置为1,同时由于要更改显示的时间状态,将使用到的一个临时缓冲区buff的取出标志位flag也置为1,表示E键被按下后,要将buff缓冲区内存的时间转移到LedBuff上来显示用户设置的时间。
其余两个标志ButtonD和ButtonE为0;
若键值为数字,则跳入下一个程序段NEXT。
NEXT程序段负责完成三个功能:
设置时间、置闹钟以及时钟运行。
此程序段通过判断三个标志是否为1,来实现不同的功能。
若ButtonC为1,意味着当前是设置时钟模式,用户在按下C键之后输入的6位数字键为设置的时间;若ButtonD为1,意味着当前是设置闹钟模式,用户在按下C键之后输入的6位数字键为设置好的闹钟时间;若ButtonE为1,意味着时钟开始运行。
详情见图
6、闹钟显示功能(他人完成)
本程序段负责实现时间达到闹钟设置时间的操作,对LED显示的内容进行判断,当6个二极管显示的数字完全相同时,即满足闹钟响的条件,此时关闭中断,并将LED显示内容更改为“888888”,显示10S后将LED恢复为响之前的状态,打开中断,继续运行时钟
7、8259初始化及中断设置(独立负责)
8259芯片:
在该系统中,8259主要担负着处理8253的一秒时间的脉冲信号,通过8253的每秒的刺激下向CPU发送中断请求,进而CPU处理担负时间计算的中断子程序,即可完成每秒钟时间自加1秒的功能,因此8259的初始化设置应为:
MOVAL,13H
MOVDX,Port0
OUTDX,AL;icw1
MOVAL,08H
MOVDX,Port1
OUTDX,AL;icw2
MOVAL,0BH
OUTDX,AL
MOVAL,7FH;IRQ7
OUTDX,AL
在接收到8253的脉冲后,需要执行的中断程序功能为对LED显示的数字进行判断,显示合理的数值,即要满足显示秒的LED管显示的最大值为59,显示分钟的最大值为59,显示时钟的最大值为23,最大时间不能超过23:
59:
59。
具体判断方法见“时间值合理的判断”
8、8253定时器设置(他人完成)
8253芯片:
在系统中定时/计数芯片8253主要与CPU及中断扩展芯片8259之间存在着连接关系。
8253主要担负着时间计时的功能,通过对分频单元提供的频率信号进行方法产生一秒时间为周期的脉冲信号。
三、功能流程图:
1、主程序流程图(他人完成)
2、LED显示子程序流程图(他人完成)
3、按键处理子程序流程图(独立负责)
4、中断子程序-时间计数子程序流程图(合作完成)
4、结果讨论:
1、实验结果:
程序运行,数码管开始从000000走表,按C键后显示‘——————’开始对时钟进行初始值设置,设置完成后按D键后,LED显示‘——————’进入闹钟设置状态,在设置完闹钟后按E键开始运行,LED管显示为设置好的时间并接收8253的中断,实现不断走表。
当显示时间达到闹钟时间时,LED管显示‘888888’,在闪烁10S结束闹钟状态,再次显示时间,并开始走表。
2、问题解决:
自己遇到的问题:
在测试C、D、E三个功能键时常常出现误输入的情况,为便于查看用户输入的值,在用户按下相应的功能键时,将LED显示为此时显示‘——————’,用户依次输入6个数字,相应地,在LED上由左向右依次显示用户输入的数字,方便查看用户是否输入了自己想测试的时间。
组员遇到的问题:
调试程序时发现时钟初始值可以设置,但是初始值设置完后时钟并没有走表,于是将8253的输出端的线接入至手动的单脉冲的发生器,进行手动给8259刺激,结果时钟开始随手按动开始走表,可以断定该8253芯片可能已经损坏,换了个试验箱后遇到了同样的情况,直至换了功能正常的实验箱后实验现象才正确展现。
附录:
实验代码:
(完整的源程序)
CODESEGMENT
ASSUMECS:
CODE,DS:
CODE,ES:
CODE
;org5000h
Port0EQU0FFE0H
Port1EQU0FFE1H
port00equ0FFF0H
port33equ0FFF3H
OUTSEGequ0ffdch;段控制口
OUTBITequ0ffddh;位控制口/键扫口
IN_KEYequ0ffdeh;键盘读入口
org3400h
LedBufdb6dup(?
);显示缓冲
CBufdb6dup(0fh)
bufdb6dup(?
);临时存放时刻
buttonCDB02H;若C键被按则置1
buttonDDB03H;若D键被按则置1
buttonEDB00H;若E键被按则置1
flagDB00h;时间从BUF取出到LEDBUF标志
cflagDB00h
Start:
;movcflag,00
movLedBuf+0,00h;开启时显示"000000"
movLedBuf+1,00h
movLedBuf+2,00h
movLedBuf+3,00h
movLedBuf+4,00h
movLedBuf+5,00h
movsi,0
;;;;;;;;;;;;;;;;;;;;;;;;初始化;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pushax
pushdx
MOVDX,port33
MOVAL,36H
OUTDX,AL
MOVDX,port00
MOVAL,00H
OUTDX,AL
MOVAL,4BH
OUTDX,AL
popdx
popax
CLI
MOVAX,OFFSETINT8259
MOVBX,003CH
MOV[BX],AX
MOVBX,003EH
MOVAX,0000H
MOV[BX],AX
CALLFOR8259
STI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
con8:
CALLDIS
callGetKey;扫描键盘并读取键值
cmpal,20h;检测是否按下按键
jzcon8
andal,0fh;显示键码
cmpal,0dh;d:
设置闹钟
jzsetD
cmpal,0ch;c:
设置时钟先时后分
jzsetC
cmpal,0eh;e:
时钟运行
jnzzhong;CDE均不是,则跳转到NEXT
jmpsetE
setD:
movbuttonD,01h
MOVbuttonC,00h
MOVbuttonE,00h
hui:
movcx,6
movsi,6
pushax
moval,LedBuf[si];之前代码声明过,si为0,所以此处si将依次为0,1,2,3,4,5
movbuf[si],al;依次把LEDBUF里的时分秒存到BUF
popax
incsi
loophui
movsi,00h
movLedBuf+0,11h;开启时显示"------"
movLedBuf+1,11h
movLedBuf+2,11h
movLedBuf+3,11h
movLedBuf+4,11h
movLedBuf+5,11h
calldis
CLI;关中断,进入设置闹钟模式
jmpcon8
zhong:
jmpnext
setC:
MOVbuttonC,01h
MOVbuttonD,00h
MOVbuttonE,00h
movsi,00h
movLedBuf+0,11h;开启时显示"------"
movLedBuf+1,11h
movLedBuf+2,11h
movLedBuf+3,11h
movLedBuf+4,11h
movLedBuf+5,11h
calldis
CLI;关中断,进入设置当前时间模式
jmpcon8
setE:
MOVbuttonE,01h
MOVbuttonD,00h
MOVbuttonC,00h
cmpflag,01h
jznext
STI;开中断,即确认C、D的输入值
next:
movbl,buttonD;通过判断三种标志,跳转到响应设置上
cmpbl,01h
jzwriteDE
movbl,buttonC
cmpbl,01h
jzwriteC
movbl,buttonE
cmpbl,01h
jzwriteDE
jmpcon8
;;;;;;;;;;;;;;;;;;;;;;;;;;
writeC:
mov[LedBuf+si],al
incsi
PUSHCX
MOVCX,100
DELAYc:
calldis
LOOPDELAYC
POPCX
cmpsi,06h
jnzoverC
movbuttonC,00h
overC:
jmpcon8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
writeDE:
cmpflag,01h;若取出BUF内时间标志与E键标志均为1,则把BUF的内容取回LEDBUF
jnzgoD
cmpbuttonE,01h
jzrecoverLED
goD:
cmpsi,06h
jnboverD
mov[LedBuf+si],al;显示当前按下的键值
mov[Cbuf+si],al;存入闹钟缓冲区
incsi
PUSHCX;键盘防抖
MOVCX,100
DELAYd:
calldis
LOOPDELAYD
POPCX
cmpsi,06h
jnzoverd;若SI不等06h即小于6,则跳到con8处,继续获取键值,直至6位闹钟设置完毕
MOVBUTTOND,00H;闹钟设置完毕,使D键标志失效,使其不会继续设置闹钟,并将取出BUF内时间标志置1
movflag,01h
overD:
JMPcon8
recoverLED:
cli;实现从BUF知LEDbuf功能的具体代码区
pushsi
pushcx
PUSHBX
movcx,0006h
loopD:
movbx,offsetLedBuf
pushcx
deccx
movsi,cx
popcx
movbl,Buf[si]
movLedBuf[si],bl
looploopD
PUSHCX;键盘防抖
MOVCX,100
DELAYdd:
calldis
LOOPDELAYDd
POPCX
MOVBUTTONE,00H;任务完成,是E键标志失效,取出标志失效,闹钟响标志生效
movflag,00h
MOVCflag,01h
sti
POPBX
popcx
popsi
sti
jmpcon8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
StartRing:
cli
pushsi
pushcx
callLEDtoBUF;启动闹钟显示前,存储LEDbuf
movcx,08h
loopring1:
movLedBuf+0,08h;开启时显示"888888"
movLedBuf+1,08h
movLedBuf+2,08h
movLedBuf+3,08h
movLedBuf+4,08h
movLedBuf+5,08h
pushcx;延时
MOVCX,100
DELAYring1:
calldis
LOOPDELAYring1
popcx
movLedBuf+0,010h
movLedBuf+1,010h
movLedBuf+2,010h
movLedBuf+3,010h
movLedBuf+4,010h
movLedBuf+5,010h
pushcx;延时
MOVCX,100
DELAYring2:
calldis
LOOPDELAYring2
popcx
looploopring1
callBUFtoLED;闹钟显示结束,恢复LEDbuf
;movjuRing,00h
popcx
popsi
sti
ret
judgeclock:
cmpCflag,01h;判断是否到达闹钟具体代码区
jnzNoring
moval,[LedBuf]
cmpal,[CBuf]
jnzNoring
moval,[LedBuf+1]
cmpal,[CBuf+1]
jnzNoring
moval,[LedBuf+2]
cmpal,[CBuf+2]
jnzNoring
moval,[LedBuf+3]
cmpal,[CBuf+3]
jnzNoring
moval,[LedBuf+4]
cmpal,[CBuf+4]
jnzNoring
moval,[LedBuf+5]
cmpal,[CBuf+5]
jnzNoring
jmpYesring
Noring:
jmpreturn
Yesring:
callstartring
return:
ret
LEDtoBUF:
PUSHsi
pushax
movsi,00h
LBloop:
moval,LEDbuf[si]
MOVbuf[si],al
incsi
cmpsi,06h
jnzLBloop
POPAX
POPSI
RET
BUFtoLED:
pushsi
pushax
movsi,00h
BLloop:
MOVAL,BUF[si]
movLedBuf[si],AL
INCSI
CMPSI,06H
JNZBLloop
popax
popsi
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FOR8259:
MOVAL,13H
MOVDX,Port0
OUTDX,AL;icw1
MOVAL,08H
MOVDX,Port1
OUTDX,AL;icw2
MOVAL,0BH
OUTDX,AL
MOVAL,7FH;IRQ7
OUTDX,AL
RET
;;;;;;;;;;;;;;;;;;;;;;;;中断子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INT8259:
cli
pushax
pushbx
pushcx
pushsi
;calljudgeclock
;cmpjuRing,01h
;jnznoRing1
;callStartRing
noRing1:
moval,[LedBuf+5];此处往下的代码区均无问题,无需更改
movah,0
calljudge
mov[LedBuf+5],al
movsi,4h
calljudge6
decsi
calljudge9
decsi
calljudge6
decsi
calljudge24
cmpcflag,01h
jnznoringgg
calljudgeclock
noringgg:
popsi
popcx
popbx
popax
CALLDIS
STI
IRET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
judge:
cmpal,09h
jnzLL1
moval,0
movah,1h
jmpjudge0
LL1:
incal
judge0:
ret
judge6:
moval,[LedBuf+si]
addal,ah
movah,0h
cmpal,06h
jnzLL2
moval,0
movah,1h
LL2:
mov[LedBuf+si],al
ret
judge9:
moval,[LedBuf+si]
addal,ah
movah,0h
cmpal,0ah
jnzLL3
moval,0
movah,1h
LL3:
mov[LedBuf+si],al
ret
judge24:
moval,[LedBuf+0]
cmpal,2
jzLL4
calljudge9
moval,[LedBuf+0]
addal,ah
movah,0h
mov[LedBuf+0],al
jmpL24
LL4:
moval,[LedBuf+1]
addal,ah
movah,0h
cmpal,4h
jnzLL5
moval,0
mov[LedBuf+0],al
mov[LedBuf+1],al
JMPL24
LL5:
mov[LedBuf+1],al
L24:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetKey:
;键扫子程序
moval,0ffh;关显示口
movdx,OUTSEG
outdx,al
movbl,0
movah,0feh
movcx,8
key1:
moval,ah
movdx,OUTBIT
outdx,al
shlal,1
movah,al
nop
nop
nop
nop
nop
nop
movdx,IN_KEY
inal,dx
notal
nop
nop
andal,0fh
jnzkey2
incbl
loopkey1
nkey:
moval,20h
ret
key2:
testal,1
jekey3
moval,0
jmpkey6
key3:
testal,2
jekey4
moval,8
jmpkey6
key4:
testal,4
jekey5
moval,10h
jmpkey6
key5:
testal,8
jenkey
moval,18h
key6:
addal,bl
cmpal,10h
jncfkey
movbx,offsetKeyTable
xlat
fkey:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DIS:
pushax
pushcx
pushsi
movsi,0h
MOVCL,20H;10000b选种某一位7段二极管
MOVBX,OFFSETLEDbuf
DIS1:
MOVAL,[BX+si]
PUSHBX
MOVBX,OFFSETLEDmap
XLAT;换码指令
POPBX
MOVDX,outseg