《微机系统与汇编语言》 课程设计 实时时钟的设计与实现.docx
《《微机系统与汇编语言》 课程设计 实时时钟的设计与实现.docx》由会员分享,可在线阅读,更多相关《《微机系统与汇编语言》 课程设计 实时时钟的设计与实现.docx(14页珍藏版)》请在冰豆网上搜索。
《微机系统与汇编语言》课程设计实时时钟的设计与实现
《微机系统与汇编语言》
课程设计
题目:
实时时钟的设计与实现
姓名:
班级:
学号:
2013年12月25日
内容要求:
1.设计内容
设计并实现实时时钟并通过LED显示时、分、秒。
2.设计要求
①、通过8254产生1s信号中断信号。
②、每秒钟产生中断,在中断子程序中修改时间。
③、在LED上显示时、分、秒。
④、通过键盘修改时钟。
三.总体设计
1.设计思路:
初始化8259A,将中断子程序入口地址写入中断向量表.
使用8254的计数器0,方式0计数,输入CLK0=18.432KHz,计数初值等于48H.端口OUT0连接到SIR1(即从8259A的IR1).一秒钟后,输出高电平,请求中断,中断响应后,中断子程序将内存中存储的时间的秒+1,同时控制分和时进位.通过转换数据格式,将时间打入内存中6个LED灯对应的位置,同时8254再次开始计数.中断结束.
使用8255A控制LED灯的显示,循环读取内存中的6位LED灯存储信息,显示、清屏、扫描键盘.通过键盘调节时间,读取按键码,调整数据格式,修改内存中的时间,在下一秒刷新时间时,显示修改后的时间.
注:
(第一次用8259A的主片的MIR7接口,第二次使用从片的SIR1接口.)
(1)如果使用8259A的主片的MIR7接口请求中断,向中断向量表的003CH和003EH分别写入中断服务子程序的偏移地址和段基址,初始化主片的ICW2=08H,其中,中断类型码的高五位是00001B(计算方法是3CH÷4),中断服务子程序结束时,OUT20H,20H;(结束中断).
(2)如果使用8259A的从片的SIR1接口请求中断,向中断向量表的00C4H和00C6H分别写入中断服务子程序的偏移地址和段基址,初始化主片的方法不变,初始化从片的ICW2=30H,中断类型码高五位是00110B(计算方法是C4H÷4),中断服务子程序结束时,执行OUT0A0H,20H和OUT20H,20H;(结束中断).
2.硬件连接图
图一
图二
图三
3.
软件流程图
4.程序代码
代码如下:
MY8255_AEQU0600H
MY8255_BEQU0602H
MY8255_CEQU0604H
MY8255_CONEQU0606H
A8254EQU06C0H;计数器0的接口地址
CON8254EQU06C6H;控制口
SSTACKSEGMENTSTACK
DW64DUP(?
)
SSTACKENDS
DATASEGMENT
TEMPWORDDW0000H;放置当前要调的是哪一位
TEMPTDB01H,00H,00H;临时数据
TIMEDB00H,00H,00H;时分秒
DTABLEDB3FH,06H,5BH,4FH,66H,6DH,7DH,07H;定义16进制数字
DB7FH,6FH,77H,7CH,39H,5EH,79H,71H
DATAENDS
CODEEGMENT
ASSUMECS:
CODE,DS:
DATA
START:
PUSHDS
PUSHSI
MOVAX,0000H
MOVDS,AX
MOVAX,OFFSETIRQ7;取中断入口地址
MOVSI,00C4H;中断矢量地址
MOV[SI],AX;填IRQ7的偏移矢量
MOVAX,CS;段地址
MOVSI,00C6H
MOV[SI],AX;填IRQ7的段地址矢量
CLI
POPSI
POPDS
;初始化主片8259
MOVAL,11H
OUT20H,AL;ICW1
MOVAL,08H
OUT21H,AL;ICW2
MOVAL,04H;表明,IR2接口上接从片
OUT21H,AL;ICW3
MOVAL,01H
OUT21H,AL;ICW4
;从片
MOVAL,11H
OUT0A0H,AL;ICW1
MOVAL,30H
OUT0A1H,AL;ICW2
MOVAL,02H;02H=00000010B
OUT0A1H,AL;ICW3(中断类型码是010,中断源是IR2)
MOVAL,01H
OUT0A1H,AL;ICW4=10100001B
MOVAL,0FDH
OUT0A1H,AL;OCW1=11111101B(=0FDH)只有IR1不被屏蔽
MOVAL,6BH;=01101011B
OUT21H,AL;主8259OCW1(IR7,IR4,IR2不被屏蔽)
STI
;以下内容为时钟显示
MOVAX,DATA
MOVDS,AX
MOVSI,3000H
MOVAL,00H
MOV[SI],AL;清显示缓冲
MOV[SI+1],AL
MOV[SI+2],AL
MOV[SI+3],AL
MOV[SI+4],AL;第二个LED
MOV[SI+5],AL;第一个LED
LEADI,TIME
MOVDX,MY8255_CON;写8255控制字
MOVAL,81H;10000001BA口,B口方式0,C口下半部输入,其它口做输出
OUTDX,AL
;计数器
PUSHDX
PUSHAX
MOVDX,CON8254
MOVAL,00110000B;计数器0,16位计数,方式0,2进制
OUTDX,AL
MOVDX,A8254
MOVAL,00H;计数器初值是18432(十进制)
OUTDX,AL;写低8位
MOVAL,48H;写高8位
OUTDX,AL
STI
POPAX
POPDX
BEGIN:
CALLDIS;调用显示子程序
CALLCLEAR;清屏
CALLCCSCAN;扫描
JNZINK1
JMPBEGIN
INK1:
ALLDIS
CALLDALLY
CALLDALLY
CALLCLEAR
CALLCCSCAN
JNZINK2;有键按下,转到INK2
JMPBEGIN
;确定按下键的位置
INK2:
MOVCH,0FEH
MOVCL,00H
COLUM:
MOVAL,CH
MOVDX,MY8255_A
OUTDX,AL
MOVDX,MY8255_C
INAL,DX;IN为输入字节或字
L1:
TESTAL,01H;isL1?
JNZL2
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,00H;==L4
ADDAL,CL
CALLSETIME;用来确定是调时,还是调分,还是调秒,还是清零
JMPCONTINUE
KCODE:
ADDAL,CL
CALLPUTBUF
CONTINUE:
PUSHAX
KON:
CALLDIS;调用显示子程序
CALLCLEAR;清屏
CALLCCSCAN;扫描
JNZKON
POPAX
NEXT:
INCCL;次数加1
MOVAL,CH
TESTAL,08H
JZKERR
ROLAL,1;左移
MOVCH,AL
JMPCOLUM
KERR:
JMPBEGIN
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,0DFH
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
INCSI
POPDX
MOVAL,DL
TESTAL,01H
JZOUT1
RORAL,1
MOVDL,AL
JMPAGAIN
OUT1:
POPAX
RET
DALLY:
PUSHCX;延时子程序
MOVCX,0006H
T1:
MOVAX,009FH
T2:
DECAX
JNZT2
LOOPT1
POPCX
RET
PUTBUF:
PUSHSI
PUSHDX
LEASI,TEMPT
;TEMPT有3个字节,第一个字节记录输入数据是十位还是个位,
;第二和第三个数据放置十位和个位的值
MOVAH,[SI]
CMPAH,01H
JZPUT1
JMPPUT2
PUT1:
MOV[SI+1],AL
MOVAH,02H
MOV[SI],AH
JMPGOBACK
PUT2:
MOVAH,01H
MOV[SI],AH
MOV[SI+2],AL
MOVAL,[SI+1]
MOVDL,0AH;=10
MULDL;AX=DL*AL
MOVAH,[SI+2]
ADDAL,AH;AL当前放的是两次输入的正确的时间,2位
LEASI,TEMPWORD
MOVSI,[SI]
MOV[SI],AL
JMPGOBACK
GOBACK:
POPDX
POPSI
RET
SETIME:
;找出最后一行阵列按的是第几个,确定调整时分秒
PUSHAX
PUSHSI
LEASI,TEMPT
MOVAH,01H
MOV[SI],AH
LEASI,TEMPWORD
LEADI,TIME
CMPAL,00H
JNZL41
MOV[SI],DI
CALLSETIMEND
L41:
CMPAL,01H
JNZL42
INCDI
MOV[SI],DI
CALLSETIMEND
L42:
CMPAL,02H
JNZL43
INCDI
INCDI
MOV[SI],DI
CALLSETIMEND
L43:
MOVSI,DI;时钟全部置0
MOVAH,00H
MOV[SI],AH
MOV[SI+1],AH
MOV[SI+2],AH
SETIMEND:
POPSI
POPAX
RET
IRQ7:
;中断服务子程序,自动修改时间
STI
PUSHSI
PUSHAX
PUSHDX
MOVDX,CON8254
MOVAL,00110000B;计数器0,16位计数,方式0,2进制
OUTDX,AL
MOVDX,A8254
MOVAL,00H;计数器初值是18432(十进制)
OUTDX,AL;写低8位
MOVAL,48H;写高8位
OUTDX,AL
MOVDL,00111100B;=60
MOVDH,00011000B;=24
LEASI,TIME
MOVAX,0000H;清空
MOVAL,[SI+2];取得时间,秒
ADDAL,01H;秒+1
DIVDL;取模60
MOV[SI+2],AH;AH=余数(模),装回去
MOVAH,[SI+1];取时间,分
ADDAL,AH;AL=秒位的进位(=1或0),分+1或0
MOVAH,00H
DIVDL;取模60
MOV[SI+1],AH;AH=模(余数),装回去
MOVAH,[SI];小时
ADDAL,AH;取分位进位
MOVAH,00H;防止混乱
DIVDH;取模24
MOV[SI],AH;模(余数)=新时间,装回去
;将时钟时间写入到6个内存块儿中
LEADI,TIME
MOVSI,3000H
MOVDL,00001010B;=10
MOVAX,0000H
MOVAL,[DI+2];读取秒
DIVDL
MOV[SI],AH;放余数
MOV[SI+1],AL;放商
MOVAX,0000H
MOVAL,[DI+1];读取分
DIVDL
MOV[SI+2],AH
MOV[SI+3],AL
MOVAX,0000H
MOVAL,[DI];读取小时
DIVDL
MOV[SI+4],AH
MOV[SI+5],AL
POPDX
POPAX
POPSI
MOVAL,20H
OUT0A0H,AL
OUT20H,AL;中断结束命令
IRET
CODEENDS
ENDSTART
4.心得体会
在这次的课程设计中我们遇到的最大的困难是如何产生中断,而且我们对中断向量表的装载还比较模糊,对中断的初始化、具体设置、中断返回还不是很清楚,以致程序设计一度陷入停滞状态,不知如何是好。
通过向老师、同学询问和自己翻书查看,终于对中断的内容有了深刻的了解。
本次课程设计中,了解到了编写程序时需要的耐心。
此次实验是对之前所学习到的汇编内容的一次大的考验,从中掌握了许多以前所未了解到的许多知识,巩固了许多之前学到的知识。