重新发一遍:STC12C4052AD自带EEPROM批量读取异常,汇编语言版本,向大家求助。
;*************************************************************************************;*************************************************************************************
;以下内容为STC12C4052内置EEPROM的读写操作有关程序
;读一字节,调用前需打开 IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
Byte_Read:
MOV ISP_CONTR,#ENABLE_IAP ;打开 IAP 功能, 设置 Flash 操作等待时间
MOV ISP_CMD, #ISP_IAP_BYTE_READ;设置为IAP/ISP/EEPROM字节读模式命令
MOV ISP_ADDRH,DPH ;设置目标单元地址的高8位地址
MOV ISP_ADDRL,DPL ;设置目标单元地址的低8位地址
;CLR EA
MOV ISP_TRIG, #46H ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV ISP_TRIG,#0B9H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
MOV A, ISP_DATA ;读出的数据在IAP_DATA单元中,送入累加器A
;SETB EA
CALL ISP_Disable ;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
RET
;------------------------------------------------
;字节编程,调用前需打开 IAP 功能,入口:DPTR = 字节地址, A=须编程字节的数据
Byte_Program:
MOV ISP_CONTR, #ENABLE_IAP ;打开 IAP 功能, 设置 Flash 操作等待时间
MOV ISP_CMD, #ISP_IAP_BYTE_PROGRAM ;设置为IAP/ISP/EEPROM字节编程模式命令
MOV ISP_ADDRH, DPH ;设置目标单元地址的高8位地址
MOV ISP_ADDRL, DPL ;设置目标单元地址的低8位地址
MOV ISP_DATA, A ;要编程的数据先送进ISP_DATA寄存器
;CLR EA
MOV ISP_TRIG, #46H ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV ISP_TRIG, #0B9H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
;SETBEA
CALL ISP_Disable ;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
RET
;------------------------------------------------
;擦除扇区, 入口:DPTR = 扇区地址
Sector_Erase:
MOV ISP_CONTR, #ENABLE_IAP ;打开 IAP 功能, 设置 Flash 操作等待时间
MOV ISP_CMD, #03H ;设置为IAP/ISP/EEPROM扇区擦除模式命令
MOV ISP_ADDRH, DPH ;设置目标单元地址的高8位地址
MOV ISP_ADDRL, DPL ;设置目标单元地址的低8位地址
;CLR EA
MOV ISP_TRIG, #46H ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV ISP_TRIG, #0B9H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
;SETBEA
CALL ISP_Disable ;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
RET
;------------------------------------------------
ISP_Disable:
;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
MOV ISP_CONTR, #0 ;关闭 IAP 功能
MOV ISP_CMD,#0 ;清命令寄存器,使命令寄存器无命令,此句可不用
MOV ISP_TRIG, #0 ;清命令触发寄存器,使命令触发寄存器无触发,此句可不用
MOV ISP_ADDRH, #0FFH ;送地址高字节单元为00,指向非EEPROM区
MOV ISP_ADDRL, #0FFH ;送地址低字节单元为00,防止误操作
RET
;------------------------------------------------
;预写数据要保存在A中
STC12_EEPROM_WRITE: ;请记住:只有“扇区擦除”才能将“0”擦除为“1”
MOV DPTR, #DATA_FLASH_START_ADDRESS;将EEPROM测试起始地址送DPTR数据指针
CALL Sector_Erase
MOV DPTR, #DATA_FLASH_START_ADDRESS;将EEPROM测试起始地址送DPTR数据指针
CALLByte_Program ;字节编程
RET
;------------------------------
;读出的数据保存在A中
STC12_EEPROM_READ:
MOV DPTR, #DATA_FLASH_START_ADDRESS;将EEPROM测试起始地址送DPTR数据指针
CALLByte_Read
RET
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;STC12EEP批量写入子程序
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STC12_EEP_WR_BAT:
MOV DPTR,#1200H ;选择STC12C4052AD第二扇区的首地址
CALL Sector_Erase
MOV R0,#IR_KEY_0 ;预写入的数据的首地址
MOV R7,#0BH ;预写入的数据长度
MOV DPTR,#1200H ;选择STC12C4052AD第二扇区的首地址
MOV ISP_CONTR, #ENABLE_IAP ;打开 IAP 功能, 设置 Flash 操作等待时间
WR_BAT1:
; PUSH ACC
MOV ISP_CMD, #ISP_IAP_BYTE_PROGRAM ;设置为IAP/ISP/EEPROM字节编程模式命令
MOV ISP_ADDRH, DPH ;设置目标单元地址的高8位地址
MOV ISP_ADDRL, DPL ;设置目标单元地址的低8位地址
MOV A,@R0
MOV ISP_DATA, A ;要编程的数据先送进ISP_DATA寄存器
CLR EA
MOV ISP_TRIG, #46H ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV ISP_TRIG, #0B9H ;送完A5h后,ISP/IAP命令立即被触发起动
CALLNOP_DELAY
SETBEA
INC DPTR
INC R0
; POP ACC
DJNZ R7,WR_BAT1
CALL ISP_Disable ;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
RET
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;STC12EEP批量读入子程序
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STC12_EEP_RD_BAT: ;STC12EEP批量读入子程序
MOV DPTR,#1200H ;选择STC12C第二扇区的首地址
MOV R0,#IR_KEY_0 ;预写入的数据的首地址
MOV R7,#0BH ;预写入的数据长度
MOV ISP_CONTR,#ENABLE_IAP ;打开 IAP 功能, 设置 Flash 操作等待时间
RD_BAT1:
; PUSH ACC
MOV ISP_CMD, #ISP_IAP_BYTE_READ;设置为IAP/ISP/EEPROM字节读模式命令
MOV ISP_ADDRH,DPH ;设置目标单元地址的高8位地址
MOV ISP_ADDRL,DPL ;设置目标单元地址的低8位地址
CLR EA
MOV ISP_TRIG, #46H ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV ISP_TRIG,#0B9H ;送完A5h后,ISP/IAP命令立即被触发起动
MOV A, ISP_DATA ;读出的数据在IAP_DATA单元中,送入累加器A
SETB EA
MOV @R0,A
CALL NOP_DELAY
INC DPTR
INC R0
; POP ACC
DJNZ R7,RD_BAT1
CALL ISP_Disable ;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
RET mcu:stc12c4052ad,晶振:12M
上面的子程序
Byte_Read:
Byte_Program:
Sector_Erase:
ISP_Disable:
应该没有问题,因为调用单个字节的读写子程序 STC12_EEPROM_WRITE: 和STC12_EEPROM_READ:没有问题,
就是在调用后面的STC12_EEP_WR_BAT:和STC12_EEP_RD_BAT: 是出了问题,不知道是没写进去还是没读出来
麻烦高手给我看看问题出在哪里,多谢。 哥们 你真牛 都用汇编 帮你顶顶 问题的具体情况貌似都没说清楚,究竟发生了什么情况?
程序我粗看好像没有大的问题,给你看看我成功用在STC12C56系列和12C5A60系列中的程序,注意读写操作的启动命令是不一样的,看下DATASHEET。同时因为我要保存的数据不多,地址也是固定的,因此没有用DPTR来传递地址,而是直接在程序中给定了。但读写操作原理是一样的!
;=====================================================================
;读取参数
LOAD_DATA:
MOV ISP_CONTR,#080H ;允许ISP操作
MOV ISP_ADDRH,#00H ;FLASH地址高八位
MOV ISP_ADDRL,#00H ;FLASH地址低八位
MOV ISP_CMD,#1 ;字节读
MOV R1,#DISET0
MOV R0,#16
LDA0: LCALL FLASH_OPERATE
MOV @R1,ISP_DATA
INC ISP_ADDRL
INC R1
DJNZ R0,LDA0
MOV ISP_CONTR,#0 ;禁止ISP操作
LD_OVER:RET
;=====================================================================
;=====================================================================
SAVE_DATA:
MOV ISP_CONTR,#080H ;允许ISP操作
MOV ISP_ADDRH,#00H ;FLASH地址高八位
MOV ISP_ADDRL,#00H ;FLASH地址低八位
MOV ISP_CMD,#3 ;擦除扇区
LCALL FLASH_OPERATE
INC ISP_ADDRL
LCALL FLASH_OPERATE
MOV ISP_ADDRL,#00H ;FLASH地址低八位
MOV ISP_CMD,#2 ;FLASH操作代码是写入字节
MOV R1,#DISET0
MOV R0,#16
SDA0: MOV ISP_DATA,@R1
LCALL FLASH_OPERATE
INC ISP_ADDRL
INC R1
DJNZ R0,SDA0
MOV ISP_CONTR,#0 ;禁止ISP操作
RET
;=====================================================================
;=====================================================================
;FLASH读写操作
FLASH_OPERATE:
MOV ISP_TRIG,#5AH
MOV ISP_TRIG,#0A5H ;开始读写操作
LCALL DELAY_1US
RET
;===================================================================== 回复【3楼】bigeblis
-----------------------------------------------------------------------
谢谢3楼的朋友,现在碰到的情况就是调用前面的单个字节的读和写都没有问题,调用后面的批量读写程序就有问题,不知道是没有写进去还是没有读出来。
感觉你的程序写的很好,也没有那么多的参数传递和保护,改天试试你的这种方法。再次感谢!
页:
[1]