📄 eeprom.asm
字号:
$LIST
;--------------------------------------------------------------
; Eeprom.asm(for 8051 ASM)
;
; 功能: I2C总线Eeprom驱动汇编程序 for 8051 serial
;
; Copyright(c) 2002-2003 Xiamen Yealink Network Technology Co,.Ltd
; By:Stonelu 2003.5.5
;--------------------------------------------------------------
$include (805Xasm.inc)
;使用此模块要定义存储器类型,本软件支持智能页写模式
;bioEepromSDA equ P2.4; //数据线
;boEepromSCL equ P2.5; //24C16的时钟脚
;boEepromWP equ P2.6; //写保护线
;--------------------------------------
;AT24C01/02 cnEepromBlockBytes EQU 8
;AT24C04/08/16 cnEepromBlockBytes EQU 16
;AT24C32/64 cnEepromBlockBytes EQU 32
;AT24C128/256 cnEepromBlockBytes EQU 64
;--------------------------------------
cnEepromBlockBytes equ 64
mEEprom32Up256 equ 1 ;是 32,64,128,256
;---- 硬件定义
;EXTRN BIT (boEepromSCL) ;24C16的时钟脚
;EXTRN BIT (bioEepromSDA) ;数据线
;EXTRN BIT (boEepromWP) ;写保护线
;--- 子程序
;EXTRN CODE (_Delay10ms) ;延时10ms (只能使用A,B,R7)
;EXTRN CODE (_Delay6us) ;延时6us (不能使用任何变量)
;EXTRN CODE (_IncR23)
;~~~
PUBLIC _EepromRD ;单个字节读 _EepromRD(R2R3)
PUBLIC _EepromWR ;单个字节写 _EepromWR(R2R3,ACC)
PUBLIC _EepromWRX ;单个字节写 _EepromWR(R2R3,ACC)
PUBLIC _EepromBlockRead ;块读 _EepromBlockRead(R2R3,R0,ACC)
PUBLIC _EepromBlockWrite ;块写 _EepromBlockWrite(R2R3,R0,ACC)
PUBLIC _EepromBlockReadX ;块读 _EepromBlockRead(R2R3,R0,ACC)
PUBLIC _EepromBlockWriteX ;块写 _EepromBlockWrite(R2R3,R0,ACC)
PUBLIC _IncR23 ;R23++(R2=H)
PUBLIC _DecR23 ;R23--(R2=H)
EXTRN CODE (ResetSysWDT)
EXTRN DATA (SoftWDTimer)
EepromBseg SEGMENT BIT
RSEG EepromBseg
bEepUseXD: dbit 1 ;使用外部Ram标志
;==============================================================
EepromCseg SEGMENT CODE
RSEG EepromCseg
;--------------------------------------------------------------
; _EepromBlockRead 从EEprom读取一块数据
;
; in R2 = High Address EEpROM高位地址
; R3 = Low Address EEpROM低位地址
; R0 = 存放数据的内部RAM指针
; ACC = 要读取的个数
; out C=0 OK A=R5 读取的数据
; =1 Error
; used ACC,B,R0,R1,R6,R7
;--------------------------------------------------------------
_EepromBlockReadX:
setb bEepUseXD
sjmp LEepromBlockRead01
_EepromBlockRead:
clr bEepUseXD
LEepromBlockRead01:
setb boEEpromWP ;防止误写入
sjmp _EepromBlockWrite05
;--------------------------------------------------------------
; _EepromRD 从EEprom读取一个数据
;
; in R2 = High Address EEpROM高位地址
; R3 = Low Address EEpROM低位地址
; out C=0 OK A=R5 读取的数据
; =1 Error
; used ACC,B,R0,R1,R6,R7
;--------------------------------------------------------------
_EepromRD:
clr bEepUseXD
setb boEEpromWP
sjmp _EepromWR05
;--------------------------------------------------------------
; _EepromWR 写一字节到eeprom
;
; in R2 = High Address EEpROM高位地址
; R3 = Low Address EEpROM低位地址
; ACC 写入EEpROM的数据
; out C=0 OK (A=R5)
; =1 Error
; used ACC,B,R0,R1,R6,R7
;--------------------------------------------------------------
USING 0 ;使用寄存器0
_EepromWRX:
setb bEepUseXD
sjmp LEepromWR01
_EepromWR:
clr bEepUseXD
LEepromWR01:
clr boEEpromWP
mov R1,A ;将要写入的数放在R5数据
_EepromWR05:
mov A,#AR1
mov R0,A ;R0为R1的地址
mov A,#1
sjmp _EepromBlockWrite05
;--------------------------------------------------------------
; _EepromBlockWrite 写一块内容到eeprom
;
; in R2 = High Address EEpROM高位地址
; R3 = Low Address EEpROM低位地址
; R0 = 要写入的内容指针
; ACC 写入EEpROM的字节长度
; out C=0 OK R0=R0+len(写入的长度)
; =1 Error
; used ACC,B,R0,R1,R6,R7
;--------------------------------------------------------------
_EepromBlockWriteX:
setb bEepUseXD
sjmp LEepromBlockWrite01
_EepromBlockWrite:
clr bEepUseXD
LEepromBlockWrite01:
clr boEEpromWP
_EepromBlockWrite05:
mov R6,A
LEepromBlockWrite10:
; LCALL _FeeWatchDog
mov A,#0
lcall _EepromStartDevice ;送start和device 命令
jc LEepromBlockWrite40
LEepromBlockWrite12:
if mEEprom32Up256
mov A,R2
lcall _SendByteACK ;等待确认信号,送数据高位地址
jc LEepromBlockWrite40
endif
mov A,R3 ;送数据低位地址
lcall _SendByteACK
jc LEepromBlockWrite40
;--- 读操作
jnb boEEpromWP,LEepromBlockWrite30
mov A,#1
lcall _EepromStartDevice ;EEpROM再次进入开始状态,并送读命令
jc LEepromBlockWrite40
LEepromBlockWrite26:
lcall _ReadByte ;读取数据
jnb bEepUseXD,LEepromBlockWrite26A
movx @R0,A
sjmp LEepromBlockWrite26B
LEepromBlockWrite26A:
mov @R0,A
LEepromBlockWrite26B:
inc R0
lcall _IncR23 ;inc DPTR
djnz R6,LEepromBlockWrite28 ;R6!=0 branch
lcall _EEpromStop
sjmp LEepromBlockWrite38 ;数据已经读完
LEepromBlockWrite28:
lcall _OutputACK ;读取下一个数
sjmp LEepromBlockWrite26
;--- 写操作
LEepromBlockWrite30:
jnb bEepUseXD,LEepromBlockWrite30A
movx A,@R0
sjmp LEepromBlockWrite30B
LEepromBlockWrite30A:
mov A,@R0
LEepromBlockWrite30B:
lcall _SendByteACK ;将数据写入EEpROM
jc LEepromBlockWrite40
inc R0
lcall _IncR23
dec R6
cje R6,#0,LEepromBlockWrite32 ;判断数据已经写完
mov A,R3
anl A,#(cnEepromBlockBytes-1)
jnz LEepromBlockWrite30 ;表示一页没有完成
LEepromBlockWrite32:
lcall _EepromStop ;EEpROM进入停止状态
mov R7,#200
LEepromBlockWrite34: ;查询,是否已经写结束
push AR7
mov A,#0
lcall _EEpromStartDevice
pop AR7
jnc LEepromBlockWrite36
djnz R7,LEepromBlockWrite34
sjmp LEepromBlockWrite40 ;测试,如果200次查询没通过,认为错误
LEepromBlockWrite36:
cjne R6,#0,LEepromBlockWrite12
lcall _EEpromStop ;因为查询,所以要停止
;--- 读写完成(OK出口)
LEepromBlockWrite38:
setb boEEpromWP
clr C
ret
;--- 读写错误返回出口
LEepromBlockWrite40:
setb boEEpromWP
;///
setb boEepromSCL
setb bioEepromSDA
;///
setb C
ret
;===== _EEpromStartDevice
; in: ACC=0 发送读命令
; =1 发送写命令
; out C=0 OK
; =1 Error,NO ACKR
_EEpromStartDevice:
push ACC
lcall _EEpromStart
pop ACC
_EEpromDevcie:
mov B,A ;in ACC=0 Write =1 Read
if mEEprom32Up256 ;=1 要兼容24C32/64/128/256操作
mov A,#10100000B ;送器件地址
else
mov A,R2
anl A,#111B
rl A
orl A,#10100000b ;送器件地址
endif
orl A,B
sjmp _SendByteACK ;等待确认信号,送数据高位地址
;===== _SendByteACK
; in: ACC 发送的数据,并等待ACK
; para: T=90us
; out C=0 OK
; =1 Error,NO ACKR
_SendByteACK:
mov R7,#8
SDBY12: rlc A ;写数据字节
mov bioEepromSDA,C
lcall _Delay6us ;_Delay6us
setb boEepromSCL
lcall _Delay6us
clr boEepromSCL
djnz R7,SDBY12
sjmp _EepromACK
;===== _EepromACK
; out C=0 OK
; =1 Error
; para T=10us
; used R7
_EepromACK:
setb bioEepromSDA
setb boEepromSCL
mov R7,#5
LEepromACK12:
jnb bioEepromSDA,LEepromACK20 ;延迟20us
djnz R7,LEepromACK12 ;2
clr boEepromSCL
setb C
ret
LEepromACK20:
clr boEepromSCL
clr C
ret
;===== _ReadByte
; out ACC 读取的数据
; para: T=90us
_ReadByte:
mov R7,#8
LReadByte10:
setb boEepromSCL ;1
setb bioEepromSDA ;1
nop ;1
nop ;1
mov C,bioEepromSDA ;2 读取数据
clr boEepromSCL ;1
rlc A ;1
djnz R7,LReadByte10 ;2
ret
;==== _EepromStart
; para: T=24us
_EepromStart:
clr boEepromSCL
nop
setb bioEepromSDA
setb boEepromSCL
lcall _Delay6us
clr bioEepromSDA
lcall _Delay6us
clr boEepromSCL
ret
;===== _EepromStop
; para: T=30us
_EepromStop:
clr boEepromSCL
lcall ResetSysWDT ;Reset WDT
mov SoftWDTimer,#00
;nop
clr bioEepromSDA
setb boEepromSCL
lcall _Delay6us
setb bioEepromSDA
lcall _Delay6us
; clr boEepromSCL
ret
;==== _OutputACK 向Eeprom发一ACK信号
_OutputACK:
clr bioEepromSDA
lcall _Delay6us
setb boEepromSCL
lcall _Delay6us
clr boEepromSCL
setb bioEepromSDA
ret
;==== _IncR23
; in R23 R2=H,R3=L
; out R23=R23+1
_IncR23:
inc R3
cjne R3,#0,LIncR2310
inc R2
LIncR2310:
ret
;==== _DecR23
;in R23 R2=H,R3=L
;out R23=R23-1
_DecR23:
dec R3
cjne R3,#0ffH,LDecR2310
dec R2
LDecR2310:
ret
_Delay6us:
nop
nop
if mOSC22d1184
nop
nop
nop
nop
nop
nop
nop
nop
endif
ret
;****************************************************************
$LIST
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -