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

    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

    总结

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