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

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产生中断设置时间,再将设置的时间存储在时间变量中,时间就设置好了。

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 ;定义数据段

TAB DB 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

SEC DB 0 ;初始化

HOUR DB 0

MIN DB 0

N_TIME DB 20 DUP(0)

Z_TIME DB 20 DUP(0)

N_S DB 30

N_M DB 0

N_H DB 0

TIMER DB 10 DUP(0)

DUAN DB 0

BUF DB 3 DUP(0)

DATA ENDS

SSTACK SEGMENT STACK ;堆栈段

DW 256 DUP(?)

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 [SI], AX ;填IRQ7的偏移矢量

MOV AX, SEG MIR7 ;段地址

MOV SI, 003EH

MOV [SI], AX ;填IRQ7的段地址矢量

;MIR6中断

MOV AX, OFFSET MIR6 ;取中断入口地址

MOV SI, 0038H ;中断矢量地址

MOV [SI], AX ;填IRQ6的偏移矢量

MOV AX, SEG MIR6 ;段地址

MOV SI, 003AH

MOV [SI], AX ;填IRQ6的段地址矢量

;MIR2中断

MOV AX, OFFSET SIR1 ;取中断入口地址

MOV SI, 00C4H ;中断矢量地址

MOV [SI], AX ;填SIR1的偏移矢量

MOV AX, SEG SIR1 ;段地址

MOV SI, 00C6H

MOV [SI], 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 [SI+1],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 [SI],AL ;清显示缓冲

MOV [SI+1],AL

MOV [SI+2],AL

MOV [SI+3],AL

MOV [SI+4],AL

MOV [SI+5],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,[SI]

INC AL

MOV [SI],AL

CMP AL,7 ;AL与6相比较

JE B2

JNZ INK2 ;有键按下,转到INK2

JMP BEGIN

;========================================

;确定按下键的位置

;========================================

B2: MOV AL,0

MOV [SI],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?

JNZ L2

MOV AL,00H ;L1

JMP KCODE

L2: TEST AL,02H ;is L2?

JNZ L3

MOV AL,04H ;L2

JMP KCODE

L3: TEST AL,04H ;is L3?

JNZ L4

MOV AL,08H ;L3

JMP KCODE

L4: TEST AL,08H ;is L4?

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,[SI]

MOV BX,OFFSET TAB

AND AX,00FFH

ADD BX,AX

MOV AL,[BX]

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 [SI],AL

MOV CX,SEG DUAN ;取DUAN的段地址

MOV DS,CX

MOV SI,OFFSET DUAN ;取DUAN的地址偏移量

MOV BX,[SI]

MOV CX,SEG N_TIME ;取DUAN的段地址

MOV DS,CX

MOV SI,OFFSET N_TIME ;取DUAN的地址偏移量

MOV [SI+BX],AL

MOV DX,[SI+BX]

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 [SI],AL ;清显示缓冲

MOV [SI+1],AL

MOV [SI+2],AL

MOV [SI+3],AL

MOV [SI+4],AL

MOV [SI+5],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,[SI]

INC AL

MOV [SI],AL

CMP AL,7 ;AL与7相比较

JE B3

JNZ INK4 ;有键按下,转到INK2

JMP BEGIN_U

;========================================

;确定按下键的位置

;========================================

B3: MOV AL,0

MOV [SI],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?

JNZ U2

MOV AL,00H ;L1

JMP KCODE1

U2: TEST AL,02H ;is L2?

JNZ U3

MOV AL,04H ;L2

JMP KCODE1

U3: TEST AL,04H ;is L3?

JNZ U4

MOV AL,08H ;L3

JMP KCODE1

U4: TEST AL,08H ;is L4?

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,[SI]

MOV BX,OFFSET TAB

AND AX,00FFH

ADD BX,AX

MOV AL,[BX]

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 [SI],AL

MOV CX,SEG DUAN ;取DUAN的段地址

MOV DS,CX

MOV SI,OFFSET DUAN ;取DUAN的地址偏移量

MOV BX,[SI]

MOV CX,SEG TIMER ;取DUAN的段地址

MOV DS,CX

MOV SI,OFFSET TIMER ;取DUAN的地址偏移量

MOV [SI+BX],AL

MOV DX,[SI+BX]

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,[SI]

INC AL

MOV [SI],AL

CMP AL,100 ;AL与100相比较

JNE TRNED ;若相等,则跳转

MOV AL,0 ;不等则向下执行

MOV [SI],AL

MOV AL,[SI+1]

ADD AL,1

DAA ;十进制调整,用于加法

MOV [SI+1],AL

CMP AL,60H

JNE TRNED

MOV AL,0

MOV [SI+1],AL

MOV AL,[SI+2]

ADD AL,1

DAA

MOV [SI+2],AL

CMP AL,60H

JNE TRNED

MOV AL,0

MOV [SI+2],AL

MOV AL,[SI+3]

ADD AL,1

DAA

MOV [SI+3],AL

CMP AL,24H

JNE TRNED

MOV AL,0

MOV [SI+3],AL

TRNED:

MOV AL,[SI+1]

MOV SEC,AL

MOV AL,[SI+2]

MOV MIN,AL

MOV AL,[SI+3]

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,[BX+SI]

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,[BX+SI]

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,[BX+SI]

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,[BX+SI]

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,[BX+SI]

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,[BX+SI]

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,[SI+1]

ROL BL,04

MOV AL,0

MOV AL,[SI+2]

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,[SI+3]

ROL BL,04

MOV AL,0

MOV AL,[SI+4]

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,[SI+5]

ROL BL,04

MOV AL,0

MOV AL,[SI+6]

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 [BX] ;取出频率值计算计数初值,0F4240H / 输出频率

MOV DX,B8254

OUT DX,AL ;装入计数初值

MOV AL,AH

OUT DX,AL

MOV DL,[DI] ;取出演奏相对时间,调用延时子程序

CALL DALLY2

ADD BX,2

INC DI

CMP WORD PTR [BX],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

总结

以上所述是小编给大家介绍的汇编语言实现电子闹钟思路详解,希望对大家有所帮助!

以上是 汇编语言实现电子闹钟思路详解 的全部内容, 来源链接: utcz.com/z/361450.html

回到顶部