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

📄 stc89c52@eprom.asm

📁 电器定时,时间自由设定,并通过LED显示年、月、日、时、分、秒。
💻 ASM
字号:
;           定时断电程序				                              *
;  Date :  2007.10.15  STC89C52@12MHZ晶振       		            *    
;  Create by :Spence Deng   				                        *
; Bit10h=0@30day,Bit11h=0@90day,Bit12h=0@180day                  *
;  Bit10h\11h\12h,all=1@360day                                    *
;  P2.5=0,CLR eprom 26h=#00h向EPROM写入一天,42h=0向Eprom写入一小时*
;******************************************************************
;************************************************************
;                 变量地址分配
;*********************************************************
  OneS_		equ	39h	;设置每秒计数器的地址
  Hour		equ	3ah	;设置小时计数器的地址
  Minute		equ	3bh	;设置分钟计数器的地址
  Second		equ	3ch	;设置秒计数器的地址
  D_			equ	3Dh	;设置天计数器的地址
  M_			equ	3eh	;设置月计数器的地址
  M_1			bit	p1.2	;一个月定时断电0有效
  M_6			bit	p1.1	;半年定时断电
  EXT			bit	p0.0	;定时输出1,0ON,1OFF
  EXT_		bit	p0.1	;定时输出2,0OFF,1ON
  Working	bit	p0.2
  working_	bit	p0.3	;测试板内显示
  LEDS		bit	p1.0
  LEDM		bit	p1.1
  LEDH		bit	p1.2
  LEDD		bit	P1.4
  ledm_    	bit     p1.6
  sjh			bit	p2.7
  sjd			bit	p2.6
;-----------------看门狗专用寄存器--------------------------
	WDT_contr	data	0e1h
;================Eprom=============================
;------------------------------------------------
;定义与IAP 有关的特殊功能寄存器
 ISP_DATA	EQU 0E2H
 ISP_ADDRH 	EQU 0E3H
 ISP_ADDRL 	EQU 0E4H
 ISP_CMD 	EQU 0E5H
 ISP_TRIG  	EQU 0E6H
 ISP_CONTR 	EQU 0E7H
;------------------------------------------------
;定义常量
;------------------------
 ENABLE_ISP 	EQU 81H ;<20MHz

 DEBUG_DATA 	EQU 5AH
 ADDH    	data 2FH
 ADDL		data 2EH

;------------------------
;选择 MCU 型号
DATA_FLASH_START_ADDRESS EQU 2000H ;STC89C/LE52RC
STC8952 equ 2000H
;------------------------------------------------
ORG  0000H
AJMP POWERON_REST
org  000bh
jmp  TimeInt	;跳到中断处理程序
;------------------------------------------------
 ORG 0080H
POWERON_REST:
 MOV SP,#060H 		;堆栈指针指向 0E0H 单元
 MOV ONES_,#125		;8ms*125=1s
 clr a			;     \
 mov hour,a		;小时  \
 mov minute,a	;分钟   }清零 
 mov second,a	;分钟  /
 mov D_,a		;天数 /
 mov 20h,a
 mov 21h,a
 mov 22h,a
 MOV 28H,A
 mov a,#0ffh
 mov p1,a
 mov p2,a
 mov p3,a
 mov 26h,a
 mov 27h,a
 mov 30h,a
 mov dptr,#DATA_FLASH_START_ADDRESS
 MOV ADDH,DPH
 MOV ADDL,DPL
 jb  p2.5,prst1    ;开机如果2。5为0擦除扇区
 lcall Sector_Erase;擦除第一扇区
 lcall dis_clreprom
 lcall clreprom_2th
 lcall dis_clreprom
 JMP PRST2
prst1:
 lcall red_eprom   ;jmp to请回天数
PRST2:
 lcall WDTsetup
 lcall setup

;************************************
;   Use Timer 0 Mode 1
;   400us interrupt
;************************************
start:

	mov 	tmod,#00000001b;
	mov 	th0,#0E3h;
	mov 	tl0,#39h;
	mov 	ie, #82h;            开全局中断
	setb  tr0;                 开定时中断
;*****************************************
main:
 clr ext
 setb ext_
; clr	working
 clr	working_
 mov a,26h
 jnz main1
 lcall addday
main1:
 jnb 42h,main2
 lcall addhours
main2:
 lcall chkoff
 lcall display
MOV WDT_CONTR, #00111110B ; 喂狗,
ljmp main



;************************************************

clreprom:
mov p1,#00h
MOV DPTR, #DATA_FLASH_START_ADDRESS
ACALL Sector_Erase ;擦除扇区, (DATA_FLASH_START_ADDRESS) != #DEBUG_DATA
MOV DPTR, #DATA_FLASH_START_ADDRESS
lcall delay
mov p1,#0ffh
ret
witeprom:

;MOV A, P3 ;写入 flash 的数据为 DEBUG_DATA
;ACALL Byte_Program ;字节编程
;ret
;************************************************
;+++++++++++擦除第二扇区+++++++++++++++++++++++
clreprom_2th:
 push  dph
 push	 dpl
 mov	 dptr,#2200h
 lcall Sector_Erase;擦除第二扇区
 pop	dpl
 pop	dph
ret
;------------------------------------------------
;读一字节
;调用前需打开 IAP 功能
;入口:DPTR = 字节地址
;返回:A = 读出字节
Byte_Read:
 MOV 	ISP_CONTR, #ENABLE_ISP 	;打开 IAP 功能, 设置 Flash 操作等待时间
 MOV 	ISP_CMD, #01 		;在EPROM命令寄存器送1为读出数据
 MOV 	ISP_ADDRH, DPH 		;Fill page address in ISP_ADDRH & ISP_ADDRL
 MOV 	ISP_ADDRL, DPL
 CLR 	EA
 MOV 	ISP_TRIG, #46H 		;Trigger ISP processing
 MOV 	ISP_TRIG, #0B9H 	;Trigger ISP processing
 NOP
 MOV 	A, ISP_DATA 		;数据在ISP_DATA
 SETB 	EA
				;Now in processing.(CPU will halt here before completing)
 ACALL  IAP_Disable 		;关闭 IAP 功能, 清与 ISP 有关的特殊功能寄存器
 RET
;------------------------------------------------
;字节编程
;调用前需打开 IAP 功能
;入口:DPTR = 字节地址, A= 须编程字节的数据
Byte_Program:
 MOV 	ISP_CONTR, #ENABLE_ISP ;打开 IAP 功能, 设置 Flash 操作等待时间
 MOV 	ISP_CMD, #02H 	       ;Select Byte Program Mode
 MOV 	ISP_ADDRH, DPH 	       ;Fill page address in ISP_ADDRH & ISP_ADDRL
 MOV 	ISP_ADDRL, DPL
 MOV 	ISP_DATA, #00H       ;数据进ISP_DATA
 CLR 	EA
 MOV 	ISP_TRIG, #46H 	       ;Trigger ISP processing
 MOV 	ISP_TRIG, #0B9H        ;Trigger ISP processing
 NOP
 SETB 	EA
 ACALL 	IAP_Disable 	       ;关闭 IAP 功能, 清与 ISP 有关的特殊功能寄存器
 RET
;------------------------------------------------
;擦除扇区, 入口:DPTR = 扇区地址
Sector_Erase:
 MOV 	ISP_CONTR, #ENABLE_ISP  ;打开 IAP 功能, 设置 Flash 操作等待时间
 MOV 	ISP_CMD, #03H 		;Select Page Erase Mode
 MOV 	ISP_ADDRH, DPH 		;Fill page address in ISP_ADDRH & ISP_ADDRL
 MOV 	ISP_ADDRL, DPL
 CLR 	EA
 MOV 	ISP_TRIG, #46H 		;Trigger ISP processing
 MOV 	ISP_TRIG, #0B9H 	;Trigger ISP processing
 NOP
 SETB 	EA
 ACALL 	IAP_Disable 		;关闭 IAP 功能, 清与 ISP 有关的特殊功能寄存器
 RET
;------------------------------------------------
Trigger_ISP:
 CLR EA
 MOV ISP_TRIG, #46H 	;Trigger ISP processing
 MOV ISP_TRIG, #0B9H 	;Trigger ISP processing
 NOP
 SETB EA
 RET
;------------------------------------------------
 IAP_Disable: 		;关闭 IAP 功能, 清与 ISP 有关的特殊功能寄存器
 MOV ISP_CONTR, #0 	;关闭 IAP 功能
 MOV ISP_CMD, #0
 MOV ISP_TRIG, #0
 RET
;------------------------------------------------
Delay:
push	acc
push	02h
push	01h
push	00h
 CLR A
 MOV R0, A
 MOV R1, A
 MOV R2, #02H
 Delay_Loop:
 DJNZ R0, Delay_Loop
 DJNZ R1, Delay_Loop
 DJNZ R2, Delay_Loop
pop	00h
pop	01h
pop	02h
pop	acc
 RET

;**********************************************
;  定时器Timer0中断服务程序(此程序每8ms执行一次)
;**********************************************
TimeInt:
	mov 	th0,#0E3h		;重新加载定时参数
	mov 	tl0,#39h;
	push 	acc
	push 	psw			;保护累加器及程序状态字的内容
	setb 	rs0			;选择工作寄存器组1,
	clr  	rs1			;这样可保护原工作寄存器组(0组)的内容
	djnz 	OneS_,NotoneSecond	;中断了125次了吗?即够1秒了吗?
	mov 	OneS_,#125		;如够1秒则重新设置"OneSecondCounter"计数器
	call 	Clock               	;调用将时钟内容加1秒的子程序
	NotoneSecond:
	pop  	psw
	pop 	 acc                   ;恢复累加器及程序状态字的内容
	reti                           ;中断返回
;*********************************************
;            时钟内容加1秒的子程序
;****************************************************
Clock:
   jnb		sjh,hours
   jnb		sjd,days
;+++++++++++++秒+++++++++++++++++++++++++
   mov	 a,Second	;将原秒值送入a
   add	 a,#1		;加1秒
   setb	 00h		;作秒显示标志位
   mov 	 Second,a
   cjne	 a,#3cH,NotOverFlow;够60秒了吗?
   mov 	 Second,#0	   ;够了则将秒值清0
;+++++++++++++分++++++++++++++++++++++++++
   mov 	a,Minute
   add 	a,#1
   setb	01h	   		;作分显示标志位
   mov 	Minute,a       	  	 ;分钟加1
   cjne a,#3cH,NotOverFlow 	;够60分了吗?
   mov 	Minute,#0	 	;够了则将分值清0
;+++++++++++++小时++++++++++++++++++++++++++
Hours:
   mov 	a,Hour
   add 	a,#1			;小时加1
	setb	42h		;作为写入EPROM标志
   setb	02h			;作小时显示标志位
   mov 	Hour,a		
   cjne a,#18H,NotOverFlow	;够24小时吗?
   mov 	Hour,#0			;够了则将小时值清0
;++++++++++++++天+++++++++++++++++++++++++++++
days:
	mov 	a,D_
	add 	a,#1			;天加1
	mov	26h,#00h		;作为写入EPROM标志
	setb	07h			;作天显示标志位
	mov 	d_,a			;够30天吗?
	cjne 	a,#1Eh,NotOverFlow	;够了天数清零
	mov	D_,#0
			;
	mov	a,M_
	add	a,#1
	setb	09h
	mov	m_,a



NotOverFlow:

          ret
          ;



;=========显示部分=============================

display:
	push	acc
	mov	a,oneS_		;用于检测0。5之用
;---以下用于显示EPROM写入,红色LED全亮300MS-------
   jnb	28h.0,distime
	jb		28h.1,witeproming
	mov  	29h,p3
	mov	p3,#00h
	setb	28h.1
witeproming:
	cjne	a,#100,distime
	mov	p3,29h
	clr	28h.0
	clr	28h.1
	
;---------以下显示秒钟---------------------
DISTIME:
	jnb	00h,disM	;是要显示秒吗,不要就看是否要显示分
	jb	04h,dissing	;秒已经显示了吗?如果有,就跳过吧
	clr	leds		;还没呢,就显示吧!
	setb	04h		;先做秒已显过标记,等下跳过就行啦
dissing:
	cjne	a,#3Eh,disM	;显示时间到了吗?没到看是否要显示分
	setb	leds		;时间到,关了
	clr	00h
	clr	04h		;此任务完成了哦,清除标记
;---------以下显示分钟--------------------
disM:
	jnb	01h,disH	;是要显示分吗,不要就看看是否要显示小时
	jb	05h,disMing	;分已经显示了吗?如果有,就跳过吧
	clr	ledM		;还没呢,就显示吧!
	setb	05h		;做个分已显标记,等下跳过就行啦
disming:
	cjne	a,#3Eh,disH	;显示时间到了吗?没到看是否要显示小时
	setb	ledM		;时间到,关了
	clr	01h
	clr	05h		;此任务完成了哦,清除标记
;--------以下显示小时---------------------------
dish:
	jnb	02h,disD	;是要显示小时吗,
	jb	06h,disHing	;小时已经显示了吗?如果有,就跳过吧
	clr	ledH		;还没呢,就显示吧!
	setb	06h		;做个小时已显标记,等下跳过就行啦
dishing:
	cjne	a,#3Eh,disD	;显示时间到了吗?
	setb	ledH		;时间到,关了
	clr	02h
	clr	06h		;此任务完成了哦,清除标记
;--------以下显示天-----------
disD:
	jnb	07h,dis_M
	jb	08h,disDing
	clr	working       ;┌用于每天输出一个计数信号
	clr	ledD
	setb	08h
disDing:
	cjne	a,#3eh,dis_M
	setb	ledD
	setb	working	      ;用于每天输出一个脉冲信号,用天计数
	clr	07h
	clr	08h
;----------以下显示月----------------------------
dis_M:
	jnb	09h,dis_Y
	jb	0ah,disM_1
	clr	ledM_
	setb	0ah
disM_1:
	cjne	a,#3eh,dis_Y
	setb	ledM_
	clr	09h
	clr	0ah
dis_Y:
nop
d_end:
pop acc
ret

;**************************************************************************
;++++++++++++看门狗设定++++++++++++++++++++
WDTsetup:
	MOV WDT_CONTR, #00111110B; Load initial value
;++++++++++++EPROM+++++++++++++++++++++++++++++++
;------------------------------------------------
;++++++++++++检测是否到断电时间+++++++++++++++++++
chkoff:
 push psw  ;保护现场
 push acc
 mov c,10h  ;是否设定一个月
 jc off_3  ;不是检查下一个
 mov a,addl ;是否到
 cjne a,#1eh,chkc;还要看是不是多了呢!
 ljmp off   ;到关机
off_3:
 mov c,11h  ;是否设定3个月
 jc off_6 ;不是检查下一个
 mov a,addl ;是否到
 cjne a,#5ah,chkc;还要看是不是多了呢

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -