📄 time.asm
字号:
;作者: CHRIST
;时间: 2004.10.6
;现况: 赋闲在公司
;EMAIL: ZGZ22@SOHU.COM
;程序功能:利用键盘调好时间并显示(开机自检--从0~9显示完后显示HELP,按下TIME功能键,按下ENTER键,调节时间
;调好后显示,硬件采用非总线方式,采用公司现有硬件
;基本要素:行列键盘扫描,数字键和功能键复用
;定时器复用,动态扫描,时钟芯片DS1302读写
;显示缓冲区:2FH=小数点缓冲区,2EH~29H=6位数码管显示缓冲区,28H=8个LED指示灯缓冲区
;程序用到硬件资源:P0口=段码,P2口显示与键盘复用,P1.1~P1.3=DS1302控制线,TIMER1
;崇拜偶像:杨屹老师
;常去论坛:WWW.MCU51.COM
;DS1302的编程是SPI总线的一种特殊情况,即DI和DO复用IO,DS1302晶振32.068K,一般可以不用启振电容
RST BIT P1.3;D1302片选线
DIO BIT P1.2;数据线
CLK BIT P1.1;时钟线
ORG 0000H;中断入口处理
SJMP MAIN
ORG 0003H
SJMP WINT0
ORG 000BH
SJMP WT0
ORG 0013H
SJMP WINT1
ORG 001BH
LJMP WT1;用到WT1
ORG 0023H
SJMP WSERIAL
ORG 0030H
WINT0:
WT0:
WINT1:
WSERIAL:
RETI
ORG 0050H
MAIN:
CLR A
MOV P0,A;清显示段码
CLR P1.6;蜂鸣器控制端
CLR P2.7;573选通
CLR P2.6;573选通
SETB P2.2;键盘线输入端
SETB P2.3
SETB P2.4
MOV SP,#60H;堆栈入口
MOV R0,#08H
MOV R7,#120
CLR A
M1: MOV @R0,A
INC R0
DJNZ R7,M1;RAM清零,共128位,清120BIT
MOV IE,#88H;开EA,开定时器1中断允许
MOV TMOD,#10H;定时器1控制字;方式1
MOV TL1,#80H;置定时初值
MOV TH1,#0FCH;
SETB TR1
MOV 14H,#1;14H等同于CLR RS0,SETB RS1下的R4,LED动态扫描用,具体看WT1程序
M2: MOV R7,#10;开机自检,从0~9循环后显示HELP
CLR A
MOV R4,A
M3: MOV R6,#100
MOV A,R3;
MOV 28H,A
MOV 2FH,A
MOV R0,#29H;显示缓冲区,编好动态扫描程序后,你只要把要实时显示的东西往里面放就行了
MOV R5,#6;总共6位数码管
MOV A,R4
M4: MOV @R0,A
INC R0
DJNZ R5,M4
M5: LCALL DL1;每一位数码管自检时停留的时间
LCALL DL1
DJNZ R6,M5;
INC R4;显示值从0~9,每一次递增1
DJNZ R7,M3;总共10位数字
CLR A
MOV 28H,A
MOV 2FH,A
MOV 29H,#18;P
MOV 2AH,#17;L
MOV 2BH,#14;E
MOV 2CH,#16;H
MOV 2DH,#19;19为DIS-CODE表里面的00,即不显示(显示空格)
MOV 2EH,#19
;DS1302预处理
MOV R2,#8EH;写命令字
MOV R3,#00H;写保护寄存器清0
LCALL DTW;DS1302写子程序
MOV R2,#90H;R2为命令和待操作地址,90H为充电寄存器命令
MOV R3,#0AAH;R3为待写数据,A0A0为充电方式,2个二极管,4K充电电阻
LCALL DTW
M6: NOP
LCALL KEY;扫描键盘子程序
JZ M6;无键按下循环
LCALL KJ;有键按下判断是什么功能键按下
;KJ为功能键判断子程序;KJ里调用的TIME程序为修改时间程序;KA为数字键处理程序;KEY为键盘扫描子程序
M7: LCALL DL12MS
LCALL DL12MS
LCALL DL12MS
LCALL TMR;将读出的程序送往显示缓冲区
MOV A,58H;RAM合用
ANL A,#0FH
MOV 29H,A
MOV A,58H
SWAP A
ANL A,#0FH
MOV 2AH,A
MOV 2BH,#20; :
ANL A,#0FH
MOV 2CH,A
MOV A,57H
SWAP A
ANL A,#0FH
MOV 2DH,A
SJMP M7;循环
;键盘扫描子程序;3X7键盘,数字键和功能键复用;可以看一下扫描得到的键码,键盘程序是从何立民老师老书上抄的
KEY: SETB RS0
SETB RS1
JNB 01H,KEY;因为键盘扫描和显示公用一个定时器1(定时器0还有他用);所以用判断标志位的形式复用定时器
CLR TR1 ;01H为键盘使用TIMER1标志位;定时器定时总共8段,1-键盘使用,2-LED指示灯使用,3~8-6位数码管
LCALL KEY1 ;每位数码管扫描1MS,一般数码管扫描频率大于60HZ即可,不会出现闪烁
SETB TR1 ;
RET
KS1: CLR A
MOV P0,A
SETB P2.6
CLR P2.6
MOV A,P2;读取P2.2~P2.4
CPL A
ANL A,#01CH;P2.2,P2.3,P2.4其中有一个为0吗
RET
KEY1: ACALL KS1
JNZ LK1
RET;
LK1: LCALL DL12MS ;判断是抖动吗
ACALL KS1
JNZ LK2
RET
LK2: MOV R2,#0FDH;送初始试探码,注意总共为3X7,有一位没用到
MOV R4,#00H
LK4: MOV P0,R2
SETB P2.6;选通送试探码
CLR P2.6
JNB P2.2,LONE;初始已经写1
JNB P2.3,LTWO
JNB P2.4,LTHR
SJMP NEXT;
LONE: MOV A,#00H
SJMP LKP
LTWO: MOV A,#07
SJMP LKP
LTHR: MOV A,#14
LKP: ADD A,R4
PUSH ACC
LK3: SETB P1.6;有按键蜂鸣器响
ACALL KS1
JNZ LK3
CLR P1.6
POP ACC
RET
NEXT: INC R4
MOV A,R2
JNB ACC.7,KND;7位都判断完了吗
RL A
MOV R2,A
AJMP LK4
KND: AJMP KEY1
;功能键处理
KJ: CJNE A,#17,KJ1
LCALL FN17
RET
KJ1: CJNE A,#12,KJ2
LCALL FN12
RET
KJ2: CJNE A,#4,KJ3
LCALL TIME;这里只用到TIME功能键,其他都是空,返回
RET
KJ3: CJNE A,#7,KJ4
LCALL FN7
RET
KJ4: CJNE A,#6,KJ5
LCALL FN6
RET
KJ5: CJNE A,#19,KJ6
LCALL FN19
RET
KJ6: CJNE A,#16,KJ7
LCALL FN16
RET
KJ7: CJNE A,#1,KJ8
LCALL FN1
RET
KJ8: CJNE A,#10,KJ9
LCALL FN10
RET
KJ9: CJNE A,#13,KJ10
LCALL FN13
RET
KJ10: CJNE A,#5,KJ11
LCALL FN5
RET
KJ11: CJNE A,#2,KJ12
LCALL FN2
RET
KJ12: CJNE A,#20,KJ13
LCALL FN20
RET
KJ13:
FN17:
FN12:
FN15:
FN7:
FN6:
FN19:
FN16:
FN1:
FN10:
FN13:
FN5:
FN2:
FN20: RET
;数据键处理
KA: NOP
CLR 07H;位07H,08H为ENTER EXIT键标志位
CLR 08H
LCALL KEY
JZ KA;一直在等待键盘输入
CJNE A,#8,KA0;0对应键码
CLR A;数字键0
RET
KA0: CJNE A,#17,KA1;数字键0~9
MOV A,#1;1
RET
KA1: CJNE A,#10,KA2
MOV A,#2;2
RET
KA2: CJNE A,#3,KA3
MOV A,#3;3
RET
KA3: CJNE A,#18,KA4
MOV A,#4;
RET
KA4: CJNE A,#11,KA5
MOV A,#5
RET
KA5: CJNE A,#4,KA6
MOV A,#6
RET
KA6: CJNE A,#14,KA7
MOV A,#7
RET
KA7: CJNE A,#7,KA8
MOV A,#8
RET
KA8: CJNE A,#0,KA9
MOV A,#9
RET
KA9: CJNE A,#6,KA10
SETB 07H;07h/08h是否为键盘【输入】和【退出】的标志位
RET
KA10: CJNE A,#1,KA
SETB 08H
RET
;时间调整功能键子程序
TIME: NOP
MOV 2EH,#19
TM0: LCALL TMR
MOV A,58H
ANL A,#0FH
MOV 29H,A
MOV A,58H
SWAP A
ANL A,#0FH
MOV 2AH,A
MOV 2BH,#20;显示时与分之间2点,例如8:10
MOV A,57H
ANL A,#0FH
MOV 2CH,A
MOV A,57H
SWAP A
ANL A,#0FH
MOV 2DH,A
TM1: LCALL KEY
CJNE A,#6,TM2;退出键键码
SJMP TM5
TM2: CJNE A,#1,TM1 ;确认键键码
TM3: LCALL KA
JB 07H,TM5
JB 08H,TM4
XCH A,29H;数字键输入
XCH A,2AH
XCH A,2CH
XCH A,2DH
SJMP TM3
TM4: MOV A,2AH
SWAP A
ORL A,29H
MOV 58H,A
MOV A,2DH
SWAP A
ORL A,2CH
MOV 57H,A
LCALL TMW
TM5: RET
;动态显示,利用定时器1
ORG 0300H
WT1: CLR 01H
CLR TR1
PUSH ACC
PUSH PSW
CLR RS0
SETB RS1
DJNZ R4,WT11;R4对应14H,而14H在前面主程序中=1
MOV R0,#27H
MOV R1,#01H
MOV R2,2FH;小数点缓冲区2FH,用到低6位,分别对应6位数码管的小数点亮=1,暗=0
MOV R3,#2
MOV R4,#8
CLR A
MOV P0,A
SETB P2.7
CLR P2.7;573选通
MOV P0,A
SETB P2.6
CLR P2.6;573选通
MOV TL1,#00H
MOV TH1,#0FEH;
SETB 01H
SETB 02H;判断是灯还是数码管的标志位
SJMP WT14
WT11: CLR A
MOV P0,A
SETB P2.7
CLR P2.7;573选通
MOV P0,A
SETB P2.6
CLR P2.6
MOV A,@R0
JNB 02H,WT12;02H判断是灯还是数码管
DJNZ R3,WT13
CLR 02H
WT12: MOV DPTR,#DIS_CODE;是数码管则去段码。是灯则跳过这一步
MOVC A,@A+DPTR
XCH A,R2
RRC A
XCH A,R2;R2中存的是6位数码管的对应小数点
MOV ACC.7,C;P0.7为小数点的驱动位,若小数点为1,则只要把1移到ACC.7中
WT13: MOV P0,A
SETB P2.7
CLR P2.7
MOV A,R1
MOV P0,A
SETB P2.6
CLR P2.6
RL A
MOV R1,A
INC R0
MOV TL1,#80H
MOV TH1,#0FCH
WT14: SETB TR1
POP PSW
POP ACC
RETI
DIS_CODE:;显示段码表,根据实际PCB显示部分编制
DB 07BH,0AH,037H,01FH,04EH,05DH,07DH,0BH,07FH,05FH;0~9
DB 06FH,07CH,071H,03EH,075H,065H,6EH,70H,67H,00H,05H
;A B C D E F H L P 空格 :
DL: PUSH 07H;一些延时程序;延时不一定准确
MOV R7,#250
DL0: NOP
NOP
NOP
DJNZ R7,DL0
POP 07H
RET
DL1: NOP
ACALL DL
ACALL DL
RET
DL12MS:
DLA: MOV R7,#0FFH
DLB: MOV R6,#0FFH
DLC: DJNZ R6,DLC
DJNZ R7,DLB
RET
;DS1302读写子程序
TMR: MOV R0,#54H
MOV R2,#8DH; R2中存命令字节,读“年”控制命令字
ACALL DTR
MOV A,R3;读出的字节存放在R3中
MOV @R0,A;保存在54H内存中,54H为年内容
INC R0
MOV R5,#89H;89H为读”月“命令字
MOV R7,#4
TMR1: MOV A,R5
MOV R2,A
ACALL DTR
MOV A,R3
MOV @R0,A;55H为月内容
INC R0
MOV A,R5;56H为日;57H为小时;58H为分
DEC A
DEC A
MOV R5,A
DJNZ R7,TMR1
RET
TMW: MOV R2,#8EH;R2中存命令字,R3中存待写入数据
MOV R3,#00H;写允许
ACALL DTW
MOV R2,#80H;秒寄存器最高位为0,启动振荡器
MOV R3,#00H
ACALL DTW
MOV R0,#54H
MOV R2,#8CH
MOV A,@R0
MOV R3,A
ACALL DTW
INC R0
MOV R5,#88H
MOV R7,#4
TMW1: MOV A,R5
MOV R2,A
MOV A,@R0
MOV R3,A
ACALL DTW
INC R0
MOV A,R5
DEC A
DEC A
MOV R5,A
DJNZ R7,TMW1
MOV R2,#8EH
MOV R3,#80H;禁止写,一般写完要使用此命令处理,否则当出现干扰时容易误写
ACALL DTW
RET
DTR: SETB P1.3
MOV A,R2;写入命令字节
MOV R4,#8
DTR1: RRC A
MOV DIO,C
NOP
NOP
SETB CLK
NOP
NOP
CLR CLK
DJNZ R4,DTR1
NOP
NOP
SETB DIO
CLR A
CLR C
MOV R4,#8
DTR2: MOV C,DIO
RRC A
NOP
NOP
SETB CLK
NOP
NOP
CLR CLK;时钟上升沿发送数据有效,时钟下降沿接收数据有效
NOP
NOP
DJNZ R4,DTR2
MOV R3,A;读出数据在R3中
CLR RST
RET
DTW: SETB RST;RST,片选
MOV A,R2;R2为写入命令字
MOV R4,#8
DTW1: RRC A;低位开始
MOV DIO,C;I/O
NOP
NOP
SETB CLK;SCLK
NOP
NOP
CLR CLK;时钟下降沿写入数据
DJNZ R4,DTW1
MOV A,R3
MOV R4,#8
DTW2: RRC A
MOV DIO,C
NOP
NOP
SETB CLK
NOP
NOP
CLR CLK
DJNZ R4,DTW2
NOP
NOP
CLR RST
RET
NOP
NOP
NOP
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -