何安胜 發表於 2020-2-3 10:44:39

汇编语言实现电子闹钟思路详解

<p><strong>2.1 设计思路</strong><br />
</p>
<p>首先使用8255、8254、8259 三个芯片实现电子时钟的功能,让闹钟可以正常走时;其次,在时钟的基础上添加闹铃功能、整点报时功能、设置当前时间功能;完成设计。</p>
<p><strong>2.2 设计方案</strong><br />
</p>
<p>1. 电子时钟部分:此次设计是通过对计数器8254设定计数值对脉冲进行计数,在程序里,8254工作于计数器0,方式3。接入的CLK为1MHz,设计数初值为10000,每100次中断计数一次,产生的记数时间正好是时钟每秒走过的时间。通过对中断控制器8259设置初始化命令字初值来控制中断。程序中通过移位指令来实现时、秒、分的个位和十位的独自存储,将分、秒的个位十位分别存入指定的寄存器中。比较转移指令来完成秒和分的累加。七段数码管由8255并行接口的A口进行位的选择,通过B口输出要显示的段码。这样就在6个七段数码管上分别显示时、分和秒。当1S时间到时,修改当前数码管数值,10秒时将秒的低位清零,高位加1,分和时亦是如此;到达60秒时,将秒清零,分加1,到达60分时,将分清零,小时加1,到达24小时则全部清零。</p>
<p>2. 闹钟响铃部分:对于闹钟部分,我们首先要完成数码管显示单元按键的连接和设计,让16个按键分别为0-F;再利用实验平台的单次脉冲输入KK1产生一次中断,这样就可以设置时间了。将设置好的时间储存起来,时刻与当前的时间进行比较,当时间一样时,计数器1工作,蜂鸣器蜂鸣,播放音乐,这就完成了闹钟响铃功能。</p>
<p>3. 整点报时部分:整点报时,就是在整时的时候响一次铃,当时钟整点时,无论是几点,时钟的分和秒部分都为零,所以,只要让时钟的分和秒部分与零进行比较,当他们都相等时,就代表到达整点了,可以响铃了。整点报时就完成了,本闹钟设置的整点报时时长为5秒。</p>
<p>4. 设置当前时间:本部分也用到了数码管显示单元的按键部分,只要利用之前的设计就好了,这次使用单次脉冲输入的KK2产生中断设置时间,再将设置的时间存储在时间变量中,时间就设置好了。<br />
</p>
<div class="jb51code">
<pre class="brush:plain;">
A8254 EQU 06C0H ;宏定义
B8254 EQU 06C2H
C8254 EQU 06C4H
CON8254 EQU 06C6H
MY8255_A EQU 0600H
MY8255_B EQU 0602H
MY8255_C EQU 0604H
MY8255_CON EQU 0606H
PUBLIC SEC,MIN,HOUR   
DATA SEGMENT    ;定义数据段
TABDB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H;数码表
DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H
FREQ_LIST DW 371,495,495,495,624,556,495,556,624;频率表
   DW 495,495,624,742,833,833,833,742,624
   DW 624,495,556,495,556,624,495,416,416,371
   DW 495,833,742,624,624,495,556,495,556,833
   DW 742,624,624,742,833,990,742,624,624,495
   DW 556,495,556,624,495,416,416,371,495,0
TIME_LIST DB 4, 6, 2, 4, 4, 6, 2, 4, 4;时间表
   DB 6, 2, 4, 4, 12, 1, 3, 6, 2
   DB 4, 4, 6, 2, 4, 4, 6, 2, 4, 4
   DB 12, 4, 6, 2, 4, 4, 6, 2, 4, 4
   DB 6, 2, 4, 4, 12, 4, 6, 2, 4, 4
   DB 6, 2, 4, 4, 6, 2, 4, 4, 12
SECDB 0   ;初始化      
HOUR DB 0         
MINDB 0
N_TIME DB 20 DUP(0)
Z_TIME DB 20 DUP(0)
N_SDB 30
N_MDB 0
N_HDB 0
TIMER DB 10 DUP(0)
DUAN DB 0
BUFDB 3 DUP(0)
DATA ENDS
SSTACK SEGMENT STACK;堆栈段
DW 256 DUP(&#63;)
SSTACK ENDS
CODE SEGMENT    ;代码段
ASSUME CS:CODE, SS:SSTACK,DS:DATA
START: ;8254初始化
MOV DX, CON8254   ;8254
MOV AL, 36H    ;计数器0,方式3
OUT DX, AL
;分频
MOV DX, A8254
MOV AL, 010H
OUT DX, AL
MOV AL, 27H
OUT DX, AL
;8255初始化
MOV AL,81H
MOV DX,MY8255_CON
OUT DX,AL
;MIR7中断
MOV AX, 0000H
MOV DS, AX
MOV AX, OFFSET MIR7   ;取中断入口地址
MOV SI, 003CH      ;中断矢量地址
MOV , AX      ;填IRQ7的偏移矢量
MOV AX, SEG MIR7    ;段地址
MOV SI, 003EH
MOV , AX      ;填IRQ7的段地址矢量
;MIR6中断
MOV AX, OFFSET MIR6   ;取中断入口地址
MOV SI, 0038H      ;中断矢量地址
MOV , AX      ;填IRQ6的偏移矢量
MOV AX, SEG MIR6    ;段地址
MOV SI, 003AH
MOV , AX      ;填IRQ6的段地址矢量
;MIR2中断
MOV AX, OFFSET SIR1   ;取中断入口地址
MOV SI, 00C4H      ;中断矢量地址
MOV , AX      ;填SIR1的偏移矢量
MOV AX, SEG SIR1    ;段地址
MOV SI, 00C6H
MOV , AX      ;填SIR1的段地址矢量
;8259初始化
MOV AL, 11H
OUT 20H, AL      ;ICW1
MOV AL, 08H
OUT 21H, AL
MOV AL,04H
OUT 21H,AL   ;ICW2
MOV AL, 03H
OUT 21H, AL      ;ICW4
;初始化从片8259
   MOV AL, 11H
OUT 0A0H, AL   ;ICW1
MOV AL, 30H
OUT 0A1H, AL   ;ICW2
MOV AL, 02H   
OUT 0A1H, AL   ;ICW3
MOV AL, 01H
OUT 0A1H, AL   ;ICW4
MOV AL, 0FDH
OUT 0A1H,AL    ;OCW1 = 1111 1101
   MOV AX,SEG N_TIME;取N_TIME的段地址
MOV DS,AX   
MOV SI,OFFSET N_TIME;取N_TIME的地址偏移量
MOV ,1
STI
AA1:
CALL DISP    ;调用显示子程序(disp)
CALL BJ    ;调用闹钟(bj)
CALL ZDBS   ;调用整点报时(bj)
   JMP AA1
MIR6 PROC
CLI
PUSH AX
PUSH SI
MOV AX,DATA
MOV DS,AX
   MOV SI,3000H
MOV AL,00H
MOV ,AL    ;清显示缓冲
MOV ,AL
MOV ,AL
MOV ,AL
MOV ,AL
MOV ,AL
MOV DI,3005H
MOV DX,MY8255_CON;写8255控制字
MOV AL,81H
OUT DX,AL
BEGIN: CALL DIS    ;调用显示子程序
CALL CLEAR    ;清屏
CALL CCSCAN    ;扫描
JNZ INK1
JMP BEGIN
INK1: CALL DIS
CALL KEYDALLY
CALL KEYDALLY
CALL CLEAR
CALL CCSCAN
MOV AX,SEG DUAN;取DUAN的段地址
MOV DS,AX   
MOV SI,OFFSET DUAN;取DUAN的地址偏移量,用于技计数
MOV AL,
INC AL
MOV ,AL
CMP AL,7    ;AL与6相比较
JE B2
JNZ INK2    ;有键按下,转到INK2
JMP BEGIN
;========================================
;确定按下键的位置
;========================================
B2:MOV AL,0
MOV ,AL
POP AX
POP SI
IRET
INK2: MOV CH,0FEH
MOV CL,00H
COLUM: MOV AL,CH
MOV DX,MY8255_A
OUT DX,AL
MOV DX,MY8255_C
IN AL,DX
L1:TEST AL,01H   ;is L1&#63;
JNZ L2
MOV AL,00H   ;L1
JMP KCODE
L2:TEST AL,02H   ;is L2&#63;
JNZ L3
MOV AL,04H   ;L2
JMP KCODE
L3:TEST AL,04H   ;is L3&#63;
JNZ L4
MOV AL,08H   ;L3
JMP KCODE
L4:TEST AL,08H   ;is L4&#63;
JNZ NEXT
MOV AL,0CH   ;L4
KCODE: ADD AL,CL
CALL PUTBUF
PUSH AX
KON: CALL DIS
CALL CLEAR
CALL CCSCAN
JNZ KON
POP AX
NEXT: INC CL
MOV AL,CH
TEST AL,08H
JZ KERR
ROL AL,1
MOV CH,AL
JMP COLUM
KERR: JMP BEGIN
;========================================
;键盘扫描子程序
;========================================
CCSCAN: MOV AL,00H
MOV DX,MY8255_A
OUT DX,AL
MOV DX,MY8255_C
IN AL,DX
NOT AL
AND AL,0FH
RET
;========================================
;清屏子程序
;========================================
CLEAR: MOV DX,MY8255_B
MOV AL,00H
OUT DX,AL
RET
;========================================
;显示子程序
;========================================
DIS: PUSH AX
MOV SI,3000H
MOV DL,0DFH
MOV AL,DL
AGAIN: PUSH DX
MOV DX,MY8255_A
OUT DX,AL
MOV AL,
MOV BX,OFFSET TAB
AND AX,00FFH
ADD BX,AX
MOV AL,
MOV DX,MY8255_B
OUT DX,AL
CALL KEYDALLY
INC SI
POP DX
MOV AL,DL
TEST AL,01H
JZ OUT1
ROR AL,1
MOV DL,AL
JMP AGAIN
OUT1: POP AX
RET
;====== 延时子程序 ======
KEYDALLY: PUSH CX
MOV CX,0006H
D1:MOV AX,009FH
D2:DEC AX
JNZ D2
LOOP D1
POP CX
RET
;========================================
;存键盘值到相应位的缓冲中
;========================================
PUTBUF: MOV SI,DI
MOV ,AL
MOV CX,SEG DUAN;取DUAN的段地址
MOV DS,CX   
MOV SI,OFFSET DUAN;取DUAN的地址偏移量
MOV BX,
MOV CX,SEG N_TIME;取DUAN的段地址
MOV DS,CX   
MOV SI,OFFSET N_TIME;取DUAN的地址偏移量
MOV ,AL
MOV DX,
DEC DI
CMP DI,2FFFH
JNZ GOBACK
MOV DI,3005H
GOBACK: RET
MIR6 ENDP
SIR1 PROC
CLI
PUSH AX
PUSH SI
MOV AX,DATA
MOV DS,AX
   MOV SI,3000H
MOV AL,00H
MOV ,AL    ;清显示缓冲
MOV ,AL
MOV ,AL
MOV ,AL
MOV ,AL
MOV ,AL
MOV DI,3005H
MOV DX,MY8255_CON;写8255控制字
MOV AL,81H
OUT DX,AL
BEGIN_U: CALL DIS1    ;调用显示子程序
CALL CLEAR1    ;清屏
CALL CCSCAN1    ;扫描
JNZ INK3
JMP BEGIN_U
INK3: CALL DIS1
CALL U_DALLY
CALL U_DALLY
CALL CLEAR1
CALL CCSCAN1
MOV AX,SEG DUAN;取DUAN的段地址
MOV DS,AX   
MOV SI,OFFSET DUAN;取DUAN的地址偏移量
MOV AL,
INC AL
MOV ,AL
CMP AL,7    ;AL与7相比较
JE B3
JNZ INK4    ;有键按下,转到INK2
JMP BEGIN_U
;========================================
;确定按下键的位置
;========================================
B3:MOV AL,0
MOV ,AL
POP AX
POP SI
IRET
INK4: MOV CH,0FEH
MOV CL,00H
COLUM2: MOV AL,CH
MOV DX,MY8255_A
OUT DX,AL
MOV DX,MY8255_C
IN AL,DX
U1:TEST AL,01H   ;is L1&#63;
JNZ U2
MOV AL,00H   ;L1
JMP KCODE1
U2:TEST AL,02H   ;is L2&#63;
JNZ U3
MOV AL,04H   ;L2
JMP KCODE1
U3:TEST AL,04H   ;is L3&#63;
JNZ U4
MOV AL,08H   ;L3
JMP KCODE1
U4:TEST AL,08H   ;is L4&#63;
JNZ NEXT1
MOV AL,0CH   ;L4
KCODE1: ADD AL,CL
CALL PUTBUF1
PUSH AX
KON1: CALL DIS1
CALL CLEAR1
CALL CCSCAN1
JNZ KON1
POP AX
NEXT1: INC CL
MOV AL,CH
TEST AL,08H
JZ KERR1
ROL AL,1
MOV CH,AL
JMP COLUM2
KERR1: JMP BEGIN_U
;========================================
;键盘扫描子程序
;========================================
CCSCAN1: MOV AL,00H
MOV DX,MY8255_A
OUT DX,AL
MOV DX,MY8255_C
IN AL,DX
NOT AL
AND AL,0FH
RET
;========================================
;清屏子程序
;========================================
CLEAR1: MOV DX,MY8255_B
MOV AL,00H
OUT DX,AL
RET
;========================================
;显示子程序
;========================================
DIS1: PUSH AX
MOV SI,3000H
MOV DL,0DFH
MOV AL,DL
AGAIN1: PUSH DX
MOV DX,MY8255_A
OUT DX,AL
MOV AL,
MOV BX,OFFSET TAB
AND AX,00FFH
ADD BX,AX
MOV AL,
MOV DX,MY8255_B
OUT DX,AL
CALL U_DALLY
INC SI
POP DX
MOV AL,DL
TEST AL,01H
JZ OUT2
ROR AL,1
MOV DL,AL
JMP AGAIN1
OUT2: POP AX
RET
;====== 延时子程序 ======
U_DALLY: PUSH CX
MOV CX,0006H
W1:MOV AX,009FH
W2:DEC AX
JNZ W2
LOOP W1
POP CX
RET
;========================================
;存键盘值到相应位的缓冲中
;========================================
PUTBUF1: MOV SI,DI
MOV ,AL
MOV CX,SEG DUAN;取DUAN的段地址
MOV DS,CX   
MOV SI,OFFSET DUAN;取DUAN的地址偏移量
MOV BX,
MOV CX,SEG TIMER;取DUAN的段地址
MOV DS,CX   
MOV SI,OFFSET TIMER;取DUAN的地址偏移量
MOV ,AL
MOV DX,
DEC DI
CMP DI,2FFFH
JNZ GOBACK1
MOV DI,3005H
GOBACK1: RET

SIR1 ENDP
MIR7 PROC   
STI      ;置中断标志位IF
PUSH AX   ;压栈
PUSH SI
MOV AX,SEG TIMER;取TIMER的段地址
MOV DS,AX   
MOV SI,OFFSET TIMER;取TIMER的地址偏移量
MOV AL,
INC AL
MOV ,AL
CMP AL,100    ;AL与100相比较
JNE TRNED    ;若相等,则跳转
MOV AL,0    ;不等则向下执行
MOV ,AL
MOV AL,
ADD AL,1
DAA       ;十进制调整,用于加法
MOV ,AL
CMP AL,60H
JNE TRNED
MOV AL,0
MOV ,AL
MOV AL,
ADD AL,1
DAA
MOV ,AL
CMP AL,60H
JNE TRNED
MOV AL,0
MOV ,AL
MOV AL,
ADD AL,1
DAA
MOV ,AL
CMP AL,24H
JNE TRNED
MOV AL,0
MOV ,AL
TRNED:
MOV AL,
MOV SEC,AL
MOV AL,
MOV MIN,AL
MOV AL,
MOV HOUR,AL
POP SI         ;出栈
POP AX
STI          ;置中断标志位IF
IRET         ;中断返回
ENDP
DISP:
PUSH BX
PUSH DI
PUSH AX
PUSH SI
MOV DX,MY8255_B
MOV AX,SEG TAB
MOV DS,AX
MOV BX,OFFSET TAB

MOV AL,SEC
AND AL,0FH      ;与低四位相与
MOV AH,00H   
MOV SI,AX
MOV AL,
OUT DX,AL
MOV DX,MY8255_A
MOV AL,0DFH
OUT DX,AL
CALL DALLY   
MOV AL,SEC
AND AL,0F0H
ror al,04
MOV AH,00H
MOV SI,AX
MOV AL,
MOV DX,MY8255_B
OUT DX,AL
MOV DX,MY8255_A
MOV AL,0EFH
OUT DX,AL
CALL DALLY
MOV AL,MIN
AND AL,0FH   
MOV AH,00H   
MOV SI,AX
MOV AL,
MOV DX,MY8255_B
OUT DX,AL
MOV DX,MY8255_A
MOV AL,0F7H
OUT DX,AL
CALL DALLY
MOV AL,MIN
AND AL,0F0H
ror al,04
MOV AH,00H
MOV SI,AX
MOV AL,
MOV DX,MY8255_B
OUT DX,AL
MOV DX,MY8255_A
MOV AL,0FBH
OUT DX,AL
CALL DALLY
MOV AL,HOUR
AND AL,0FH   
MOV AH,00H   
MOV SI,AX
MOV AL,
MOV DX,MY8255_B
OUT DX,AL
MOV DX,MY8255_A
MOV AL,0FDH
OUT DX,AL
CALL DALLY
MOV AL,HOUR
AND AL,0F0H
ror al,04
MOV AH,00H
MOV SI,AX
MOV AL,
MOV DX,MY8255_B
OUT DX,AL
MOV DX,MY8255_A
MOV AL,0FEH
OUT DX,AL
CALL DALLY
POP SI
POP AX
POP DI
POP BX
RET
ZDBS PROC      ;整点报时
MOV AL,MIN
CMP AL,00H
JNZ LP2

MOV AL,SEC
CMP AL,00H
JNZ LP2

MOV DX, CON8254   ;8254
MOV AL, 76H    ;计数器1,方式3
OUT DX, AL

ZD1:
MOV DX, B8254
MOV AL, 00H
OUT DX, AL
MOV AL, 09H
OUT DX, AL
MOV AL,SEC
CMP AL,05H
JE OUTZD
CALL DISP
JMP ZD1

OUTZD:
MOV AX,00H
OUT DX,AL
MOV AL,AH
OUT DX,AL
RET

LP2: RET
ZDBS ENDP

BJ PROC       ;闹铃程序
MOV AL,HOUR
MOV CX,SEG N_TIME;取DUAN的段地址
MOV DS,CX   
MOV SI,OFFSET N_TIME;取DUAN的地址偏移量
   MOV BL,
ROL BL,04
MOV AL,0
MOV AL,
OR BL,AL
CMP AL,BL
JNZ LP
MOV CX,SEG N_TIME;取DUAN的段地址
MOV DS,CX   
MOV SI,OFFSET N_TIME;取DUAN的地址偏移量
   MOV BL,
ROL BL,04
MOV AL,0
MOV AL,
OR BL,AL
MOV AL,MIN
CMP AL,BL
JNZ LP
MOV CX,SEG N_TIME;取DUAN的段地址
MOV DS,CX   
MOV SI,OFFSET N_TIME;取DUAN的地址偏移量
MOV BL,
ROL BL,04
MOV AL,0
MOV AL,
OR BL,AL
MOV AL,SEC
CMP AL,BL
JNZ LP
MOV DX, CON8254   ;8254
MOV AL, 76H    ;计数器1,方式3
OUT DX, AL
BEGIN_M: MOV BX,OFFSET FREQ_LIST
MOV DI,OFFSET TIME_LIST;装入时间表起始地址

PLAY: MOV DX,0FH   ;输入时钟为1MHz,1M = 0F4240H
MOV AX,4240H   
DIV WORD PTR    ;取出频率值计算计数初值,0F4240H / 输出频率
MOV DX,B8254
OUT DX,AL   ;装入计数初值
MOV AL,AH
OUT DX,AL
MOV DL,   ;取出演奏相对时间,调用延时子程序
CALL DALLY2
ADD BX,2
INC DI
CMP WORD PTR ,0   ;判断是否到曲末?
JE OUTPLAY
CALL DISP
JMP PLAY
OUTPLAY:MOV DX,B8254
MOV AX,00H
OUT DX,AL
MOV AL,AH
OUT DX,AL
RET
LP: RET
DALLY2 PROC      ;延时子程序
H0:MOV CX,0010H
H1:MOV AX,0FF0H
H2:DEC AX
JNZ H2
LOOP H1
DEC DL
JNZ H0
RET
DALLY2 ENDP
BJ ENDP

DALLY: PUSH CX
MOV CX,0006H
T1:MOV AX,009FH
T2:DEC AX
JNZ T2
LOOP T1
POP CX
RET
CODE ENDS</pre>
</div>
<p><span style="color: #ff0000"><strong>总结</strong></span></p>
<p>以上所述是小编给大家介绍的汇编语言实现电子闹钟思路详解,希望对大家有所帮助!</p>
                           
                            <div class="art_xg">
                              
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 汇编语言实现电子闹钟思路详解