汇编语言实现电子闹钟思路详解
2.1设计思路
首先使用8255、8254、8259三个芯片实现电子时钟的功能,让闹钟可以正常走时;其次,在时钟的基础上添加闹铃功能、整点报时功能、设置当前时间功能;完成设计。
2.2设计方案
1.电子时钟部分:此次设计是通过对计数器8254设定计数值对脉冲进行计数,在程序里,8254工作于计数器0,方式3。接入的CLK为1MHz,设计数初值为10000,每100次中断计数一次,产生的记数时间正好是时钟每秒走过的时间。通过对中断控制器8259设置初始化命令字初值来控制中断。程序中通过移位指令来实现时、秒、分的个位和十位的独自存储,将分、秒的个位十位分别存入指定的寄存器中。比较转移指令来完成秒和分的累加。七段数码管由8255并行接口的A口进行位的选择,通过B口输出要显示的段码。这样就在6个七段数码管上分别显示时、分和秒。当1S时间到时,修改当前数码管数值,10秒时将秒的低位清零,高位加1,分和时亦是如此;到达60秒时,将秒清零,分加1,到达60分时,将分清零,小时加1,到达24小时则全部清零。
2.闹钟响铃部分:对于闹钟部分,我们首先要完成数码管显示单元按键的连接和设计,让16个按键分别为0-F;再利用实验平台的单次脉冲输入KK1产生一次中断,这样就可以设置时间了。将设置好的时间储存起来,时刻与当前的时间进行比较,当时间一样时,计数器1工作,蜂鸣器蜂鸣,播放音乐,这就完成了闹钟响铃功能。
3.整点报时部分:整点报时,就是在整时的时候响一次铃,当时钟整点时,无论是几点,时钟的分和秒部分都为零,所以,只要让时钟的分和秒部分与零进行比较,当他们都相等时,就代表到达整点了,可以响铃了。整点报时就完成了,本闹钟设置的整点报时时长为5秒。
4.设置当前时间:本部分也用到了数码管显示单元的按键部分,只要利用之前的设计就好了,这次使用单次脉冲输入的KK2产生中断设置时间,再将设置的时间存储在时间变量中,时间就设置好了。
A8254EQU06C0H;宏定义 B8254EQU06C2H C8254EQU06C4H CON8254EQU06C6H MY8255_AEQU0600H MY8255_BEQU0602H MY8255_CEQU0604H MY8255_CONEQU0606H PUBLICSEC,MIN,HOUR DATASEGMENT;定义数据段 TABDB3FH,06H,5BH,4FH,66H,6DH,7DH,07H;数码表 DB7FH,6FH,77H,7CH,39H,5EH,79H,71H FREQ_LISTDW371,495,495,495,624,556,495,556,624;频率表 DW495,495,624,742,833,833,833,742,624 DW624,495,556,495,556,624,495,416,416,371 DW495,833,742,624,624,495,556,495,556,833 DW742,624,624,742,833,990,742,624,624,495 DW556,495,556,624,495,416,416,371,495,0 TIME_LISTDB4,6,2,4,4,6,2,4,4;时间表 DB6,2,4,4,12,1,3,6,2 DB4,4,6,2,4,4,6,2,4,4 DB12,4,6,2,4,4,6,2,4,4 DB6,2,4,4,12,4,6,2,4,4 DB6,2,4,4,6,2,4,4,12 SECDB0;初始化 HOURDB0 MINDB0 N_TIMEDB20DUP(0) Z_TIMEDB20DUP(0) N_SDB30 N_MDB0 N_HDB0 TIMERDB10DUP(0) DUANDB0 BUFDB3DUP(0) DATAENDS SSTACKSEGMENTSTACK;堆栈段 DW256DUP(?) SSTACKENDS CODESEGMENT;代码段 ASSUMECS:CODE,SS:SSTACK,DS:DATA START:;8254初始化 MOVDX,CON8254;8254 MOVAL,36H;计数器0,方式3 OUTDX,AL ;分频 MOVDX,A8254 MOVAL,010H OUTDX,AL MOVAL,27H OUTDX,AL ;8255初始化 MOVAL,81H MOVDX,MY8255_CON OUTDX,AL ;MIR7中断 MOVAX,0000H MOVDS,AX MOVAX,OFFSETMIR7;取中断入口地址 MOVSI,003CH;中断矢量地址 MOV[SI],AX;填IRQ7的偏移矢量 MOVAX,SEGMIR7;段地址 MOVSI,003EH MOV[SI],AX;填IRQ7的段地址矢量 ;MIR6中断 MOVAX,OFFSETMIR6;取中断入口地址 MOVSI,0038H;中断矢量地址 MOV[SI],AX;填IRQ6的偏移矢量 MOVAX,SEGMIR6;段地址 MOVSI,003AH MOV[SI],AX;填IRQ6的段地址矢量 ;MIR2中断 MOVAX,OFFSETSIR1;取中断入口地址 MOVSI,00C4H;中断矢量地址 MOV[SI],AX;填SIR1的偏移矢量 MOVAX,SEGSIR1;段地址 MOVSI,00C6H MOV[SI],AX;填SIR1的段地址矢量 ;8259初始化 MOVAL,11H OUT20H,AL;ICW1 MOVAL,08H OUT21H,AL MOVAL,04H OUT21H,AL;ICW2 MOVAL,03H OUT21H,AL;ICW4 ;初始化从片8259 MOVAL,11H OUT0A0H,AL;ICW1 MOVAL,30H OUT0A1H,AL;ICW2 MOVAL,02H OUT0A1H,AL;ICW3 MOVAL,01H OUT0A1H,AL;ICW4 MOVAL,0FDH OUT0A1H,AL;OCW1=11111101 MOVAX,SEGN_TIME;取N_TIME的段地址 MOVDS,AX MOVSI,OFFSETN_TIME;取N_TIME的地址偏移量 MOV[SI+1],1 STI AA1: CALLDISP;调用显示子程序(disp) CALLBJ;调用闹钟(bj) CALLZDBS;调用整点报时(bj) JMPAA1 MIR6PROC CLI PUSHAX PUSHSI 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 MOV[SI+5],AL MOVDI,3005H MOVDX,MY8255_CON;写8255控制字 MOVAL,81H OUTDX,AL BEGIN:CALLDIS;调用显示子程序 CALLCLEAR;清屏 CALLCCSCAN;扫描 JNZINK1 JMPBEGIN INK1:CALLDIS CALLKEYDALLY CALLKEYDALLY CALLCLEAR CALLCCSCAN MOVAX,SEGDUAN;取DUAN的段地址 MOVDS,AX MOVSI,OFFSETDUAN;取DUAN的地址偏移量,用于技计数 MOVAL,[SI] INCAL MOV[SI],AL CMPAL,7;AL与6相比较 JEB2 JNZINK2;有键按下,转到INK2 JMPBEGIN ;======================================== ;确定按下键的位置 ;======================================== B2:MOVAL,0 MOV[SI],AL POPAX POPSI IRET INK2:MOVCH,0FEH MOVCL,00H COLUM:MOVAL,CH MOVDX,MY8255_A OUTDX,AL MOVDX,MY8255_C INAL,DX 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,0CH;L4 KCODE:ADDAL,CL CALLPUTBUF PUSHAX KON:CALLDIS CALLCLEAR CALLCCSCAN JNZKON POPAX NEXT:INCCL 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,OFFSETTAB ANDAX,00FFH ADDBX,AX MOVAL,[BX] MOVDX,MY8255_B OUTDX,AL CALLKEYDALLY INCSI POPDX MOVAL,DL TESTAL,01H JZOUT1 RORAL,1 MOVDL,AL JMPAGAIN OUT1:POPAX RET ;======延时子程序====== KEYDALLY:PUSHCX MOVCX,0006H D1:MOVAX,009FH D2:DECAX JNZD2 LOOPD1 POPCX RET ;======================================== ;存键盘值到相应位的缓冲中 ;======================================== PUTBUF:MOVSI,DI MOV[SI],AL MOVCX,SEGDUAN;取DUAN的段地址 MOVDS,CX MOVSI,OFFSETDUAN;取DUAN的地址偏移量 MOVBX,[SI] MOVCX,SEGN_TIME;取DUAN的段地址 MOVDS,CX MOVSI,OFFSETN_TIME;取DUAN的地址偏移量 MOV[SI+BX],AL MOVDX,[SI+BX] DECDI CMPDI,2FFFH JNZGOBACK MOVDI,3005H GOBACK:RET MIR6ENDP SIR1PROC CLI PUSHAX PUSHSI 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 MOV[SI+5],AL MOVDI,3005H MOVDX,MY8255_CON;写8255控制字 MOVAL,81H OUTDX,AL BEGIN_U:CALLDIS1;调用显示子程序 CALLCLEAR1;清屏 CALLCCSCAN1;扫描 JNZINK3 JMPBEGIN_U INK3:CALLDIS1 CALLU_DALLY CALLU_DALLY CALLCLEAR1 CALLCCSCAN1 MOVAX,SEGDUAN;取DUAN的段地址 MOVDS,AX MOVSI,OFFSETDUAN;取DUAN的地址偏移量 MOVAL,[SI] INCAL MOV[SI],AL CMPAL,7;AL与7相比较 JEB3 JNZINK4;有键按下,转到INK2 JMPBEGIN_U ;======================================== ;确定按下键的位置 ;======================================== B3:MOVAL,0 MOV[SI],AL POPAX POPSI IRET INK4:MOVCH,0FEH MOVCL,00H COLUM2:MOVAL,CH MOVDX,MY8255_A OUTDX,AL MOVDX,MY8255_C INAL,DX U1:TESTAL,01H;isL1? JNZU2 MOVAL,00H;L1 JMPKCODE1 U2:TESTAL,02H;isL2? JNZU3 MOVAL,04H;L2 JMPKCODE1 U3:TESTAL,04H;isL3? JNZU4 MOVAL,08H;L3 JMPKCODE1 U4:TESTAL,08H;isL4? JNZNEXT1 MOVAL,0CH;L4 KCODE1:ADDAL,CL CALLPUTBUF1 PUSHAX KON1:CALLDIS1 CALLCLEAR1 CALLCCSCAN1 JNZKON1 POPAX NEXT1:INCCL MOVAL,CH TESTAL,08H JZKERR1 ROLAL,1 MOVCH,AL JMPCOLUM2 KERR1:JMPBEGIN_U ;======================================== ;键盘扫描子程序 ;======================================== CCSCAN1:MOVAL,00H MOVDX,MY8255_A OUTDX,AL MOVDX,MY8255_C INAL,DX NOTAL ANDAL,0FH RET ;======================================== ;清屏子程序 ;======================================== CLEAR1:MOVDX,MY8255_B MOVAL,00H OUTDX,AL RET ;======================================== ;显示子程序 ;======================================== DIS1:PUSHAX MOVSI,3000H MOVDL,0DFH MOVAL,DL AGAIN1:PUSHDX MOVDX,MY8255_A OUTDX,AL MOVAL,[SI] MOVBX,OFFSETTAB ANDAX,00FFH ADDBX,AX MOVAL,[BX] MOVDX,MY8255_B OUTDX,AL CALLU_DALLY INCSI POPDX MOVAL,DL TESTAL,01H JZOUT2 RORAL,1 MOVDL,AL JMPAGAIN1 OUT2:POPAX RET ;======延时子程序====== U_DALLY:PUSHCX MOVCX,0006H W1:MOVAX,009FH W2:DECAX JNZW2 LOOPW1 POPCX RET ;======================================== ;存键盘值到相应位的缓冲中 ;======================================== PUTBUF1:MOVSI,DI MOV[SI],AL MOVCX,SEGDUAN;取DUAN的段地址 MOVDS,CX MOVSI,OFFSETDUAN;取DUAN的地址偏移量 MOVBX,[SI] MOVCX,SEGTIMER;取DUAN的段地址 MOVDS,CX MOVSI,OFFSETTIMER;取DUAN的地址偏移量 MOV[SI+BX],AL MOVDX,[SI+BX] DECDI CMPDI,2FFFH JNZGOBACK1 MOVDI,3005H GOBACK1:RET SIR1ENDP MIR7PROC STI;置中断标志位IF PUSHAX;压栈 PUSHSI MOVAX,SEGTIMER;取TIMER的段地址 MOVDS,AX MOVSI,OFFSETTIMER;取TIMER的地址偏移量 MOVAL,[SI] INCAL MOV[SI],AL CMPAL,100;AL与100相比较 JNETRNED;若相等,则跳转 MOVAL,0;不等则向下执行 MOV[SI],AL MOVAL,[SI+1] ADDAL,1 DAA;十进制调整,用于加法 MOV[SI+1],AL CMPAL,60H JNETRNED MOVAL,0 MOV[SI+1],AL MOVAL,[SI+2] ADDAL,1 DAA MOV[SI+2],AL CMPAL,60H JNETRNED MOVAL,0 MOV[SI+2],AL MOVAL,[SI+3] ADDAL,1 DAA MOV[SI+3],AL CMPAL,24H JNETRNED MOVAL,0 MOV[SI+3],AL TRNED: MOVAL,[SI+1] MOVSEC,AL MOVAL,[SI+2] MOVMIN,AL MOVAL,[SI+3] MOVHOUR,AL POPSI;出栈 POPAX STI;置中断标志位IF IRET;中断返回 ENDP DISP: PUSHBX PUSHDI PUSHAX PUSHSI MOVDX,MY8255_B MOVAX,SEGTAB MOVDS,AX MOVBX,OFFSETTAB MOVAL,SEC ANDAL,0FH;与低四位相与 MOVAH,00H MOVSI,AX MOVAL,[BX+SI] OUTDX,AL MOVDX,MY8255_A MOVAL,0DFH OUTDX,AL CALLDALLY MOVAL,SEC ANDAL,0F0H roral,04 MOVAH,00H MOVSI,AX MOVAL,[BX+SI] MOVDX,MY8255_B OUTDX,AL MOVDX,MY8255_A MOVAL,0EFH OUTDX,AL CALLDALLY MOVAL,MIN ANDAL,0FH MOVAH,00H MOVSI,AX MOVAL,[BX+SI] MOVDX,MY8255_B OUTDX,AL MOVDX,MY8255_A MOVAL,0F7H OUTDX,AL CALLDALLY MOVAL,MIN ANDAL,0F0H roral,04 MOVAH,00H MOVSI,AX MOVAL,[BX+SI] MOVDX,MY8255_B OUTDX,AL MOVDX,MY8255_A MOVAL,0FBH OUTDX,AL CALLDALLY MOVAL,HOUR ANDAL,0FH MOVAH,00H MOVSI,AX MOVAL,[BX+SI] MOVDX,MY8255_B OUTDX,AL MOVDX,MY8255_A MOVAL,0FDH OUTDX,AL CALLDALLY MOVAL,HOUR ANDAL,0F0H roral,04 MOVAH,00H MOVSI,AX MOVAL,[BX+SI] MOVDX,MY8255_B OUTDX,AL MOVDX,MY8255_A MOVAL,0FEH OUTDX,AL CALLDALLY POPSI POPAX POPDI POPBX RET ZDBSPROC;整点报时 MOVAL,MIN CMPAL,00H JNZLP2 MOVAL,SEC CMPAL,00H JNZLP2 MOVDX,CON8254;8254 MOVAL,76H;计数器1,方式3 OUTDX,AL ZD1: MOVDX,B8254 MOVAL,00H OUTDX,AL MOVAL,09H OUTDX,AL MOVAL,SEC CMPAL,05H JEOUTZD CALLDISP JMPZD1 OUTZD: MOVAX,00H OUTDX,AL MOVAL,AH OUTDX,AL RET LP2:RET ZDBSENDP BJPROC;闹铃程序 MOVAL,HOUR MOVCX,SEGN_TIME;取DUAN的段地址 MOVDS,CX MOVSI,OFFSETN_TIME;取DUAN的地址偏移量 MOVBL,[SI+1] ROLBL,04 MOVAL,0 MOVAL,[SI+2] ORBL,AL CMPAL,BL JNZLP MOVCX,SEGN_TIME;取DUAN的段地址 MOVDS,CX MOVSI,OFFSETN_TIME;取DUAN的地址偏移量 MOVBL,[SI+3] ROLBL,04 MOVAL,0 MOVAL,[SI+4] ORBL,AL MOVAL,MIN CMPAL,BL JNZLP MOVCX,SEGN_TIME;取DUAN的段地址 MOVDS,CX MOVSI,OFFSETN_TIME;取DUAN的地址偏移量 MOVBL,[SI+5] ROLBL,04 MOVAL,0 MOVAL,[SI+6] ORBL,AL MOVAL,SEC CMPAL,BL JNZLP MOVDX,CON8254;8254 MOVAL,76H;计数器1,方式3 OUTDX,AL BEGIN_M:MOVBX,OFFSETFREQ_LIST MOVDI,OFFSETTIME_LIST;装入时间表起始地址 PLAY:MOVDX,0FH;输入时钟为1MHz,1M=0F4240H MOVAX,4240H DIVWORDPTR[BX];取出频率值计算计数初值,0F4240H/输出频率 MOVDX,B8254 OUTDX,AL;装入计数初值 MOVAL,AH OUTDX,AL MOVDL,[DI];取出演奏相对时间,调用延时子程序 CALLDALLY2 ADDBX,2 INCDI CMPWORDPTR[BX],0;判断是否到曲末? JEOUTPLAY CALLDISP JMPPLAY OUTPLAY:MOVDX,B8254 MOVAX,00H OUTDX,AL MOVAL,AH OUTDX,AL RET LP:RET DALLY2PROC;延时子程序 H0:MOVCX,0010H H1:MOVAX,0FF0H H2:DECAX JNZH2 LOOPH1 DECDL JNZH0 RET DALLY2ENDP BJENDP DALLY:PUSHCX MOVCX,0006H T1:MOVAX,009FH T2:DECAX JNZT2 LOOPT1 POPCX RET CODEENDS
总结
以上所述是小编给大家介绍的汇编语言实现电子闹钟思路详解,希望对大家有所帮助!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。