⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 time.asm

📁 单片机实用子程序
💻 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 + -