;* ========================================================================== *
; 东哥 单片机 学习网 网址: www.pICavr.com
; 名称:
AT93C46的汇编读写软件包
; 文件名: 93C46_8.ASM
; 程序模块已通过硬件仿真调试,方便实用.
;* ========================================================================== *
; 说明: 软件包仅适用于93C46 8位存储器结构状态,软件包可嵌入到80C51 ROM中任一空间。
; fosc = 12MHz
;----------------------------------------------------------
R31 EQU 1FH
CS EQU P1.0 ;片选端
SK EQU P1.1 ;模拟时钟信号输出端
DI EQU P1.2 ;串行数据输出端
DO EQU P1.3 ;串行数据输入端
;----------------------------------------------------------
ORG 0000H
JMP MAIN
ORG 0100H
MAIN:
MOV R0,#7FH
CLR A
MOV @R0,A
DJNZ R0,$-2
MOV SP,#60H
MAIN1:
MOV R0,#30H
MOV R7,#16
MOV A,#1
MOV @R0,A
INC R0
INC A
DJNZ R7,$-3
CALL EWNE ;擦写允许
MOV A,#01100000B ;地址"11xxxxx"
CALL INADR ;输出地址
CALL EWNE ;片擦除(将整个存储器置为"1")
MOV A,#01000000B ;片擦除地址
CALL INADREW ;输出地址
CALL DLY10ms
CALL RD16 ;读指定地址单元的数据
CALL WRITE ;将数据写入指定地址单元
CALL ERASE ;擦除(将指定地址单元置为"1")
MOV A,#01H ;地址
CALL INADREW ;输出地址
CALL DLY10ms
CALL RD16 ;读
CALL EWNE ;擦/写禁止
MOV A,#0 ;地址"00xxxxx"
CALL INADR ;输出地址
JMP MAIN1
;==========================================================
;----------------------------------------------------------
;将存在80C51内RAM 30H为首地址的16字节数据依次写入93C46首址00H的EEPROM
;注意: 93C46上电复位后,芯片处于写保护状态,所以在擦写操作前,应开启"写允许".
;否则无法写入数据.
WRITE:
MOV A,#01100000B ;地址"11xxxxx"
CALL INADR ;输出地址
MOV R0,#30H ;置源数据区首址
MOV R1,#00H ;置93C46写入单元首址
MOV R7,#16 ;字节数
CALL WRIT6
RET
;----------------------------------------------------------
;将
AT93C46 首址为00H的16字节数据读出并存入80C51以30H为首址的内RAM中
RD16: MOV R0,#20H ;置数据存储区首址
MOV A,#00H ;置93C46读出单元首地址
MOV R7,#16 ;字节数送R7
LCALL STATRD ;启动读
LCALL INADR ;输出93C46读出单元首址
RD160:
LCALL READ ;读出一个字节数据
MOV @R0,A ;存一个字节数据
INC R0 ;指向下一存储单元地址
DJNZ R7,RD160 ;判16字节数据读完否?未完继续
CLR CS ;16字节数据读完,置93C46低功耗备用状态
CALL DLY10ms ;延时10ms,以便进行芯片的其它功能操作
RET
;----------------------------------------------------------
;入口: 数据区首址在R0,93C46单元地址在R1,写入的字节数在R7中
WRIT6:
LCALL STATWR ;启动写
MOV A,R1 ;置93C46写入单元地址
LCALL INADR ;输出93C46写入地址单元
MOV A,@R0 ;读写入数据
LCALL WRIT ;写入一个字节
LCALL DLY1ms ;延时1ms
INC R0 ;指向8051下一个数据地址
INC R1 ;指向93C46下一个写入单元地址
DJNZ R7,WR61 ;判6字节数据写完否?未完继续
CLR CS ;93C46进入备用状态,降低功耗
CALL DLY10ms
RET
WR61: JB DO,WRIT6 ;判REDAY/BUSY,DO=1,写入下一字节
SJMP WR61 ;DO=0,转等待
;==========================================================
; 启动读子程序
; 说明: STATRD子程序输出启动和读操作代码"110"
;----------------------------------------------------------
STATRD:
CLR CS ;片选置低
CLR SK ;时钟置低
SETB CS
SETB DI ;置启动"1"
SETB SK ;时钟上升沿输出启动信号"1"
CLR SK
SETB SK ;时钟上升沿输出"1"
CLR SK
CLR DI ;置输出"0"
SETB SK ;时钟上升沿输出"0"
CLR SK ;时钟置低
RET
;----------------------------------------------------------
; 启动写子程序
; 说明: STATWR子程序输出启动和写操作代码"101"
;----------------------------------------------------------
STATWR:
CLR CS ;片选置低
CLR SK ;时钟置低
SETB CS ;置片选
SETB DI ;置启动"1"
SETB SK ;时钟上升沿输出启动信号"1"
CLR SK
CLR DI ;置输出"0"
SETB SK ;时钟上升沿输出"0"
CLR SK
SETB DI ;置输出"1"
SETB SK ;时钟上升沿输出"1"
CLR SK ;时钟置低
RET
;----------------------------------------------------------
; 擦写允许/禁止启动和操作代码 "100"
; 该子程序可用于: 擦写允许(EWEN)、写禁止(EWDS)、片写(WRAL)、片擦除(ERAL),
; 只是各自的地址不同而也.
; 擦写允许/禁止操作代码"100",地址"11xxxxx"/"00xxxxx"
;----------------------------------------------------------
EWNE:
CLR CS ;片选置低
CLR SK ;时钟置低
SETB CS ;置片选
SETB DI ;置启动"1"
SETB SK ;时钟上升沿输出启动信号"1"
CLR SK
CLR DI ;置输出"0"
SETB SK ;时钟上升沿输出"0"
CLR SK
CLR DI ;置输出"0"
SETB SK ;时钟上升沿输出"1"
CLR SK ;时钟置低
RET
;----------------------------------------------------------
; 擦指令ERASE 启动和操作代码 "111"
;----------------------------------------------------------
ERASE:
CLR CS ;片选置低
CLR SK ;时钟置低
SETB CS ;置片选
SETB DI ;置启动"1"
SETB SK ;时钟上升沿输出启动信号"1"
CLR SK
SETB DI ;置输出"1"
SETB SK ;时钟上升沿输出"0"
CLR SK
SETB DI ;置输出"1"
SETB SK ;时钟上升沿输出"1"
CLR SK ;时钟置低
RET
;----------------------------------------------------------
; 输出读写单元地址子程序
; 入口: 7位地址已存在A中D6~D0
;----------------------------------------------------------
INADR:
MOV R2,#7 ;置写入地址位数(存储单元8位结构时,地址为7位)
RLC A ;先左移一位,地址移至D7~D1,D0无效
IR1: CLR SK ;时钟置低
RLC A ;左移一位
MOV DI,C ;存入DI端口
SETB SK ;时钟上升沿输出至93C46DI端
DJNZ R2,IR1 ;判断7位地址写完否,未完继续
RET
;----------------------------------------------------------
; 输出擦单元地址子程序
INADREW:
CALL INADR
CLR CS
NOP
SETB CS
JNB DO,$ ; DO=0,表示编程正在进行;
; DO=1,表示该指定地址的寄存器单元已擦完,可以执行下一条指令。
RET
;----------------------------------------------------------
; 读一个字节子程序
; 出口: 8位数据存在A中
;----------------------------------------------------------
READ: CLR SK ;时钟置低
MOV R2,#8 ;置读入位数8
RD1: SETB SK ;时钟上升沿读入一位数据
NOP
MOV C,DO ;存入Cy
RLC A ;左移入A中
CLR SK ;时钟置低
DJNZ R2,RD1 ;判8位数据读完否?未完继续
RET
;----------------------------------------------------------
;确良写一个字节子程序
; 入口: 写入数据须事先存入A中.
; 若需写入多个字节数据,须在1ms后,93C46 DO 端出现高电平后才能重新启动写入.
;----------------------------------------------------------
WRIT:
MOV R2,#8 ;置写入位数8
WR1: CLR SK ;时钟置低
RLC A ;A中数据移一位至Cy中
MOV DI,C ;数据传送至DI端
nop
SETB SK ;时钟上升沿输出至93C46
DJNZ R2,WR1 ;判8位数据写完否?未完继续
CLR CS ;8位数据写完,CS下降沿启动93C46擦写
SETB CS ;CS次高位,以使DO端REDAY/BUSY状态位号有效
RET
;----------------------------------------------------------
DLY1ms: ;延时1ms子程序
MOV R31,#29 ;
L2: PUSH R31
L3: DJNZ R31,L3
POP R31
DJNZ R31,L2
RET
DLY10ms: ;延时10ms子程序
MOV R31,#100
L20: PUSH R31
L30: DJNZ R31,L30
POP R31
DJNZ R31,L20
RET
;==========================================================
END