tonyone 发表于 2011-9-22 21:14:35

重新发一遍: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

tonyone 发表于 2011-9-22 21:20:19

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: 是出了问题,不知道是没写进去还是没读出来

麻烦高手给我看看问题出在哪里,多谢。

afei8856 发表于 2011-9-26 21:38:41

哥们 你真牛 都用汇编 帮你顶顶

bigeblis 发表于 2011-9-26 22:08:48

问题的具体情况貌似都没说清楚,究竟发生了什么情况?
程序我粗看好像没有大的问题,给你看看我成功用在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
;=====================================================================

tonyone 发表于 2011-9-27 10:07:39

回复【3楼】bigeblis
-----------------------------------------------------------------------

谢谢3楼的朋友,现在碰到的情况就是调用前面的单个字节的读和写都没有问题,调用后面的批量读写程序就有问题,不知道是没有写进去还是没有读出来。

感觉你的程序写的很好,也没有那么多的参数传递和保护,改天试试你的这种方法。再次感谢!
页: [1]
查看完整版本: 重新发一遍:STC12C4052AD自带EEPROM批量读取异常,汇编语言版本,向大家求助。