亲宝软件园·资讯

展开

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

人气:1

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

总结

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

加载全部内容

相关教程
猜你喜欢
用户评论