📄 stc89c52@eprom.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 + -