📄 eeprom.asm
字号:
;/*********************** (C) COPYRIGHT 2008 GETSOON************************
;* File Name : EEPROM_EMULATE.asm
;* Author :
;* Date First Issued : 12/03/2008
;* Description : eeprom_emulate_78k0s
;**************************************************************************/
PUBLIC _EEPROMWrite
PUBLIC _EEPROMRead
;---------------------------------------------------------------------
;---------------------------------------------------------------------
;OPTBYTE CSEG AT 0081H
;
; DB 11111111B ; 保护字节: Bit(6-2) = 11111B
; ; 保护区域: None
; ; 非保护区域: Blocks 0~ 15
; ; 确定要释放block的保护
; ; 设定为EEPROM仿真
;---------------------------------------------------------------------
; 用于EEPROM的Block号 用户设定
;---------------------------------------------------------------------
EP_TBL CSEG
tEEPROM_BLOCK: ;例) 当使用block 14 和 15
DB 12 ; (设定的block必须是连续的。
DB 13 ; 设定的block不要与程序区重叠。)
tEEPROM_BLOCK_END:
;---------------------------------------------------------------------
; 用于EEPROM的Block的地址 用户设定
;---------------------------------------------------------------------
tEEPROM_BLK_ADR:
DW 00C00H ;例) block 14的起始地址
DW 00D00H ; block 15的起始地址
DW 00DFFH+1 ; block 15 + 1的结束地址
;---------------------------------------------------------------------
; 将要被写入的数据block号 用户设定
;---------------------------------------------------------------------
DATA_NO_MAX EQU 3 ;例) 当使用8个数据block 编号为 0 到 7
;---------------------------------------------------------------------
; 其它 EQU 设定
;---------------------------------------------------------------------
CMD_INTERNAL_VERIFY EQU (00000001B) ;内部校验 (比较MRG01和MRG11)
CMD_INTERNAL_VERIFY2 EQU (00000010B) ;内部校验2 (比较MRG01和MRG12)
CMD_BLOCK_ERASE EQU (00000011B) ;Block擦除
CMD_BLANK_CHECK EQU (00000100B) ;Blank检验
CMD_BYTE_WRITE EQU (00000101B) ;1字节写入
NO_ERR EQU (00000000B) ;未发现错误
ERR_FPRERR EQU (00000001B) ;PFCMD写入错误
ERR_VCERR EQU (00000010B) ;擦除/写入/内部校验错误
ERR_WEPRERR EQU (00000100B) ;保护错误
FALSE EQU (0FFH) ;异常
TRUE EQU (00H) ;正常
DATATOP EQU (2) ;数据写入起始地址
LENG EQU (4) ;数据长度
EEPROM_BLOCK_NO EQU (tEEPROM_BLOCK_END - tEEPROM_BLOCK) ;需要用到的block编号
WRITE_RETRY EQU (10) ;为写入进行的重新计数
ERASE_RETRY EQU (20) ;为擦除进行的重新计数
;---------------------------------------------------------------------
;---------------------------------------------------------------------
; RAM设定
;---------------------------------------------------------------------
EP_RAM1 DSEG saddr
b8DataBuf: DS 8 ;内部应用的缓存RAM
d2Address: DS 2 ;用于存储EEPROM 读取/写入地址的RAM
dBlockTBLNo: DS 1 ;在EEPROM 过程中用于存储正在被使用block的RAM
;读取/写入处理
ci: DS 1 ;通用目的循环计数器
d2SrcAdr: DS 2 ;在EEPROM数据查询过程中用于存储地址RAM
d2EndAdr: DS 2 ;在EEPROM数据查询过程中用于存储block的结束地址的RAM
;
d2DataAdr: DS 2 ;在EEPROM数据查询过程中用于保护最新数据地址的RAM
;
d2SetAdr: DS 2 ;在模块转换过程中用于存储数据传送目的地址的RAM
;
d2GetAdr: DS 2 ;在模块转换过程中用于存储数据传送源地址的RAM
;
d2ReadGet: DS 2 ;用于存储数据传送源地址的RAM
d2ReadSet: DS 2 ;用于存储数据传送目的地址的RAM
dNextBlockTBLNo: DS 1 ;用于存储转换目的的RAM
cj: DS 1 ; 通用目的循环计数器
d2MaskStatus: DS 2 ;用于存储掩模数据的RAM
EEPROM_PROG CSEG
;-------------------------------------------------------------------
; 函数名称: _EEPROMRead (用户访问功能)
; 输入: X = 读取数据号
; DE = 读取数据存储地址
; 输出: C = 正常完成(正确:00H)或是异常终止(错误:FFH)
; 摘要: 将指定的数据从EEPROM中读取到存储地址。
; 1. 寻找用做EEPROM的block。
; 2. 在合法的blocks中寻找最新的数据地址。
; 3. 在寻找到的地址中读取最新的数据。
;-------------------------------------------------------------------
_EEPROMRead:
PUSH HL
PUSH DE
PUSH AX
MOVW AX,SP
MOVW HL,AX
CALL !EEPROMUseBlockSearch ;寻找当前正在用于EEPROM的block
MOV A,C
MOV dBlockTBLNo,A
CMP A,#FALSE
BZ $EP_READ_FL ;异常终止
MOV E,A
MOV A,[HL]
MOV X,A
CALL !EEPROMDataSearch ;获取制定数据编号的最新数据地址
;
MOVW AX,BC
CMPW AX,#0000H ;异常终止
BZ $EP_READ_FL
INCW AX ;设定数据编号被忽略的数据地址
;
MOVW DE,AX
MOVW d2Address,AX
MOV A,[DE]
MOV C,A
MOV A,[HL+2]
XCH A,X
MOV A,[HL+3]
MOVW DE,AX
INCW AX
MOV [HL+3],A
XCH A,X
MOV [HL+2],A
MOV A,C
MOV [DE],A ;读取最新数据地址+1的数据1
MOVW AX,d2Address
INCW AX
MOVW DE,AX
MOV A,[DE]
MOV C,A
MOV A,[HL+2]
XCH A,X
MOV A,[HL+3]
MOVW DE,AX
MOV A,C
MOV [DE],A ;读取最新数据地址+3的数据2
MOV C,#TRUE ;返回值=正常完成(正确)
BR EP_READ_E
EP_READ_FL:
MOV C,#FALSE ;返回值=异常终止(错误)
EP_READ_E:
POP AX
POP DE
POP HL
RET
;-------------------------------------------------------------------
; 函数名称: _EEPROMWrite (用户访问功能)
; 输入: X = 写入数据编号
; DE = 写入数据存储地址
; 输出: C = 正常完成(正确:00H)或是异常完成(错误:FFH)
; 摘要: 把制定编号的数据从存储地址写入EEPROM。
; 1. 寻找用做EEPROM的block。
; 2. 如果没有有效地blocks,则把第一个指定的block设定为有效。
; 3. 寻找用于允许写入到有效block的地址。
; 4. 如果有效的block已满或者不能被写入,操作将转移到下一个block。
; 5. 创建写入数据。
; 6. 写入到有效的blocks。
;-------------------------------------------------------------------
_EEPROMWrite:
PUSH HL
PUSH DE
PUSH AX
MOVW AX,SP
MOVW HL,AX
CALL !SelfFlashModeOn ;设定flash模式
CALL !EEPROMUseBlockSearch ;寻找被用作EEPROM的block
MOV A,C
MOV dBlockTBLNo,A ;设定使用的block号
CMP A,#FALSE ;检验block号
BNZ $EP_WRITE_3 ;正常完成
CALL !EEPROMBlockInit ;如果当前没有应用的blocks,被指定为EEPROM的最小编号的block
;被设定为有效的block
;
MOV A,C
MOV dBlockTBLNo,A ;设定使用的block号
CMP A,#FALSE ;检验block号
BNZ $EP_WRITE_2 ;正常完成
BR EP_WRITE_FL ;异常终止
EP_WRITE_2:
MOV A,dBlockTBLNo
CALL !BlockAddressGet
ADDW AX,#DATATOP
MOVW d2Address,AX ;计算block写入的起始地址(数据起始地址+偏移量(合法/非法标志))
;
BR EP_WRITE_4
EP_WRITE_3:
MOV A,dBlockTBLNo
MOV X,#00H
XCH A,X
CALL !_EEPROMWriteTopSearch
MOVW AX,BC
MOVW d2Address,AX ;设定当前使用的表的写入地址
EP_WRITE_4:
MOV A,dBlockTBLNo
INC A
CALL !BlockAddressGet ;重新查找当前使用的block的结束地址
XCH A,X
SUB A,d2Address
XCH A,X
SUBC A,d2Address+1
CMPW AX,#LENG
BNC $EP_WRITE_6 ;比较可写入的字节编号和写入数据的长度(数据编号,分隔符,等)
;
MOV A,dBlockTBLNo
MOV X,#0
XCH A,X
CALL !EEPROMUseBlockChange ;当数据不能被写入时改变使用的block
MOV A,C
MOV dBlockTBLNo,A ;确定使用的block号
CMP A,#FALSE ;检验block号
BZ $EP_WRITE_FL ;异常终止
EP_WRITE_5:
MOV A,dBlockTBLNo
MOV X,#00H
XCH A,X
CALL !_EEPROMWriteTopSearch
MOVW AX,BC
MOVW d2Address,AX ;设定当前使用的表的写入地址
EP_WRITE_6:
MOV A,[HL] ;给写入数据缓存的EEPROM设定数据编号
MOV b8DataBuf,A
MOV A,[HL+2]
XCH A,X
MOV A,[HL+3]
MOVW DE,AX
INCW AX
MOV [HL+3],A
XCH A,X
MOV [HL+2],A
MOV A,[DE]
MOV b8DataBuf+1,A ;给写入数据缓存的EEPROM设定数据1
MOV A,[HL+2]
XCH A,X
MOV A,[HL+3]
MOVW DE,AX
MOV A,[DE]
MOV b8DataBuf+2,A ;给写入数据缓存的EEPROM设定数据2
MOV A,#00H
MOV b8DataBuf+3,A ; 给写入数据缓存的EEPROM设定定界符
MOVW DE,#b8DataBuf
MOV C,#LENG
MOVW AX,d2Address
CALL !Flash_EEPROMWrite ;向EEPROM中写入被创建的写入数据
BZ $EP_WRITE_TR
EP_WRITE_FL:
CALL !SelfFlashModeOff ;释放flash模式
MOV C,#FALSE ;返回数据 = 异常终止(错误)
BR EP_WRITE_E
EP_WRITE_TR:
CALL !SelfFlashModeOff ;释放flash模式
MOV C,#TRUE ;返回数据 = 正常完成(正确)
EP_WRITE_E:
POP AX
POP DE
POP HL
RET
;-------------------------------------------------------------------
; 函数名称: EEPROMUseBlockSearch
; 输入: 无
; 输出 : C = Block表编号(00H到FEH),异常终止(错误: FFH)
; 摘要: 寻找位于EEPROM的flash存储器中当前正在使用的block。
;-------------------------------------------------------------------
EEPROMUseBlockSearch:
PUSH HL
MOV L,#0 ;初始化循环计数器L寄存器
EP_BSRC_T:
MOV A,L
CMP A,#EEPROM_BLOCK_NO ;循环号 = EEPROM设定block的编号
BNC $EP_BSRC_FL
CALL !BlockAddressGet
MOVW DE,AX
MOV A,[DE]
MOV b8DataBuf,A
INCW DE
MOV A,[DE]
MOV b8DataBuf+1,A
EP_BSRC_2:
MOV A,b8DataBuf
CMP A,#00H
BNZ $EP_BSRC_3 ;当有效标志 = 00,
MOV A,b8DataBuf+1
CMP A,#0FFH
BNZ $EP_BSRC_3 ;当有效标志 = FF,
MOVW AX,HL
MOV A,#00H
MOVW BC,AX ;返回值 = 有效block编号
BR EP_BSRC_E
EP_BSRC_3:
INC L
BR EP_BSRC_T
EP_BSRC_FL:
MOV C,#FALSE ;返回值 = 异常完成(没有有效的block)
;
EP_BSRC_E:
POP HL
RET
;-------------------------------------------------------------------
; 函数名称: EEPROMBlockInit
; 输入: 无
; 输出: C = 正常完成(正确:00H)或是异常完成(错误:FFH)
; 摘要: 如果用于EEPROM的block都是无效的,则第一个被指定的block被
; 设定为当前应用的(有效的)。
;-------------------------------------------------------------------
EEPROMBlockInit:
PUSH HL
MOV A,!tEEPROM_BLOCK ;为EEPROM设定最小的block编号
CALL !SelfFlashBlockErase ;擦除指定的block
MOV A,C
CMP A,#TRUE
BNZ $EP_BINI_FL ;异常终止
MOV A,#00H
MOV b8DataBuf,A ;设定block有效数据
MOVW DE,#b8DataBuf
MOV C,#1
MOV A,!tEEPROM_BLK_ADR
MOV X,A
MOV A,!tEEPROM_BLK_ADR+1
CALL !Flash_EEPROMWrite ;调用EEPROM写入处理
BNZ $EP_BINI_FL ;异常完成
EP_BINI_TR:
MOV C,#TRUE ;返回值 = 正常完成(正确)
BR EP_BINI_E
EP_BINI_FL:
MOV C,#FALSE ;返回值 = 异常终止(错误)
EP_BINI_E:
POP HL
RET
;-------------------------------------------------------------------
; 函数名称: EEPROMUseBlockChange
; 输入: X = 当前使用的block的表编号
; (使用用户自行定义的为EEPROM设定的block编号)
; 输出: C = Block表编号(00H到FEH),异常终止(FFH)
; 摘要: 如果当前使用的block已经写满了数据,该函数寻找下一个block用于写入数据。
; 1. 设定下一个被使用的block。
; 2. 擦除下一个被使用的block。
; 3. 把最新的数据从有效的block传送到下一个block。
; 4. 把下一个block设定为有效。
; 5. 把当前有效的block设定为无效。
;-------------------------------------------------------------------
EEPROMUseBlockChange:
PUSH HL
MOVW HL,AX
MOV A,L ;确定下一个将被使用的block
INC A
CMP A,#EEPROM_BLOCK_NO
BC $EP_BCHG_2
MOV A,#0
EP_BCHG_2:
MOV dNextBlockTBLNo,A
MOV C,A
MOVW AX,#tEEPROM_BLOCK
XCH A,X
ADD A,C
XCH A,X
ADDC A,#0
MOVW DE,AX
MOV A,[DE]
CALL !SelfFlashBlockErase ;擦除下一个被使用的block
MOV A,#FALSE
CMP A,C
BNZ $EP_BCHG_3 ;如果擦除异常结束,
BR EP_BCHG_FL
EP_BCHG_3:
MOV A,dNextBlockTBLNo
CALL !BlockAddressGet
ADDW AX,#DATATOP
MOVW d2SetAdr,AX ;设定下一个block写入的起始地址
MOV ci,#0 ;设定下一个block写入的起始地址
EP_BCHG_T:
MOV A,ci
CMP A,#DATA_NO_MAX ;从0到DATA_NO_MAX循环
BC $EP_BCHG_J
BR EP_BCHG_9
EP_BCHG_J:
MOV A,L
MOV E,A
MOV A,ci
MOV X,A
CALL !EEPROMDataSearch ;寻找最新的数据编号地址
MOVW AX,BC
MOVW d2GetAdr,AX
CMPW AX,#0000H ;判断地址是否为除去0000H之外的其它地址(数据存在)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -