请教大家:关于STC32G汇编语言的EEPROM的读写程序
本帖最后由 newlined 于 2024-4-6 16:53 编辑大家好:我们这里有个产品,以前用的是STC8H的单片机,最近要用到CAN,所以改用STC32G的单片机,不想在读写EEPROM时遇到问题,程序好像有些跑飞。以前的程序读EEPROM时,调用方式如下:
MOV DPTR,#ADDR1 ;ADDR1是EEPROM的地址 16位
LCALL READ
MOV DATA1,A ;读出的数据放到DATA1
写入时,先擦除再写:
MOV DPTR,#ADDR1
LCALL SECTOR_ERASE ;删除扇区
;
MOV A,DATA1 ;保存
MOV DPTR,#ADDR1
LCALL WRITE
每次读写都是一个字节,为了不修改以前的主程序,我参照STC32G的例程,修改了读写程序,在主程序中用了F0寄存器,在程序中我加了PUSH PSW 和POP PSW 以保护 F0,
我修改后的程序如下:因为只用了几个字节,所以 IAP_ADDRE我直接置为0,请大家看看哪里出了问题,谢谢。
IAP_DISABLE:
MOV IAP_CONTR, #0 ; 禁止ISP/IAP操作
MOV IAP_CMD,#0 ; 去除ISP/IAP命令
MOV IAP_TRIG, #0 ; 防止ISP/IAP命令误触发
MOV IAP_ADDRE, #0FFH ; 清0地址高字节
MOV IAP_ADDRH, #0FFH ; 清0地址中字节
MOV IAP_ADDRL, #0FFH ; 清0地址低字节,指向非EEPROM区,防止误操作
RET
read:
PUSH AR2
POP PSW
MOV IAP_ADDRE, #0 ; 送地址高字节(地址需要改变时才需重新送地址)
MOV IAP_ADDRH, DPH ; 送地址中字节(地址需要改变时才需重新送地址)
MOV IAP_ADDRL, DPL ; 送地址低字节(地址需要改变时才需重新送地址)
MOV IAP_CONTR, #IAP_EN ; 允许ISP/IAP操作,送一次就够
MOV IAP_TPS, #TPS_WAIT ; 设置等待时间,
MOV IAP_CMD, #1 ; ISP读出命令送字节读命令,命令不需改变时,不需重新送命令
MOV C, EA
MOV F0, C ;保存EA
CLR EA ; 禁止中断
MOV IAP_TRIG, #0x5A ;ISP触发命令
MOV IAP_TRIG, #0xA5
NOP
NOP
NOP
NOP
MOV C, F0
MOV EA, C ; 允许中断(如果允许)
LCALL IAP_DISABLE
MOV A, IAP_DATA
POP PSW
POP AR2
RET
SECTOR_ERASE:
;扇区擦除,512字节/扇区。
PUSH PSW ;扇区中任意一个字节地址都是扇区地址。
MOV IAP_ADDRE, #0 ; 送地址高字节(地址需要改变时才需重新送地址)
MOV IAP_ADDRH, DPH ; 送地址中字节(地址需要改变时才需重新送地址)
MOV IAP_ADDRL, DPL ; 送地址低字节(地址需要改变时才需重新送地址)
MOV IAP_CONTR, #IAP_EN ; 允许ISP/IAP操作,送一次就够
MOV IAP_TPS, #TPS_WAIT ; 设置等待时间,
MOV IAP_CMD, #3 ;送扇区擦除命令
MOV C, EA
MOV F0, C ;保存EA
CLR EA ;禁止中断
MOV IAP_TRIG, #0x5A ;ISP触发命令
MOV IAP_TRIG, #0xA5
NOP
NOP
NOP
NOP
MOV C, F0
MOV EA, C ; 允许中断(如果允许)
LCALL IAP_DISABLE
POP PSW
RET
WRITE:
PUSH AR2
PUSH PSW
MOV IAP_ADDRE, #0 ; 送地址高字节(地址需要改变时才需重新送地址)
MOV IAP_ADDRH, DPH ; 送地址中字节(地址需要改变时才需重新送地址)
MOV IAP_ADDRL, DPL ; 送地址低字节(地址需要改变时才需重新送地址)
MOV IAP_CONTR, #IAP_EN ; 允许ISP/IAP操作,送一次就够
MOV IAP_TPS, #TPS_WAIT ; 设置等待时间,
MOV IAP_CMD, #2 ;送字节写命令,命令不需改变时,不需重新送命令
MOV C, EA
MOV F0, C ;保存EA
MOV IAP_DATA, A ; 送数据到IAP_DATA,只有数据改变时才需重新送
CLR EA ; 禁止中断
MOV IAP_TRIG, #0x5A ;ISP触发命令
MOV IAP_TRIG, #0xA5
NOP
NOP
NOP
NOP
MOV C, F0
MOV EA, C ; 允许中断(如果允许)
LCALL IAP_DISABLE
POP PSW
POP AR2
RET
顺便请教下,在程序中用到了 PUSH AR2这个语句,貌似AR2对应R2寄存器?英文实在太拉,那个帮助看不了{:4_167:}。 本帖最后由 zhp 于 2024-4-6 16:55 编辑
下面这句错了,应该是PUSH PSW
另外,你的子程序里面没有使用到R2,
所以不需要PUSH AR2和POP AR2
zhp 发表于 2024-4-6 16:53
下面这句错了,应该是PUSH PSW
谢谢版主,想不到是这样的错误{:4_266:}我再试试。 @ZHP,程序我修改了,比以前好多了,非常感谢,但还是运行不正常。读写EEPROM,只在主程序及主程序调用的子程序中用到,在中断中没有用到,读写EEPROM用到的寄存器DPTR(DPH,DPL),IAP_ADDRE, IAP_ADDRH,IAP_ADDRL, IAP_CONTR, IAP_TPS, IAP_CMD,IAP_DATA在中断中是不是就没有必要没有保护?在主程序和中断中都用到了A和PSW,所以在中断中我保护了ACC,PSW,以前的程序运行正常,就是换了STC32G,只要加上读写EEPROM部分,就不正常了,还有哪里我没有做到? 本帖最后由 zhp 于 2024-4-7 17:40 编辑
newlined 发表于 2024-4-7 09:14
@ZHP,程序我修改了,比以前好多了,非常感谢,但还是运行不正常。读写EEPROM,只在主程序及主程序调用的子 ...
如果你主循环和中断程序都需要同时访问EEPROM
则除了保护ACC、PDW外,IAP相关寄存器都需要保护
更好的方法是:IAP的读、写、擦除均修改为先关闭中断,再进行IAP操作
比如:IAP的读代码可作如下修改
read:
PUSH PSW
MOV C, EA
MOV F0, C ;保存EA
CLR EA ; 禁止中断
NOP
NOP
MOV IAP_ADDRE, #0 ; 送地址高字节(地址需要改变时才需重新送地址)
MOV IAP_ADDRH, DPH ; 送地址中字节(地址需要改变时才需重新送地址)
MOV IAP_ADDRL, DPL ; 送地址低字节(地址需要改变时才需重新送地址)
MOV IAP_CONTR, #IAP_EN ; 允许ISP/IAP操作,送一次就够
MOV IAP_TPS, #TPS_WAIT ; 设置等待时间,
MOV IAP_CMD, #1 ; ISP读出命令送字节读命令,命令不需改变时,不需重新送命令
MOV IAP_TRIG, #0x5A ;ISP触发命令
MOV IAP_TRIG, #0xA5
NOP
NOP
NOP
NOP
MOV A, IAP_DATA
LCALL IAP_DISABLE
MOV C, F0
MOV EA, C ; 允许中断(如果允许)
POP PSW
RET
擦除和写的代码类似修改
zhp 发表于 2024-4-7 17:39
如果你主循环和中断程序都需要同时访问EEPROM
则除了保护ACC、PDW外,IAP相关寄存器都需要保护
版主您好,我按照您的意见修改了程序,还是不行,我估计现在读写EEPROM是没有问题了,
可能是别的地方出了问题,这个程序是多年前别人从另一种单片机移植过来的,一些问题当时
没有显现出来,比如一些地址的定义?
我猜测的,我再仔细检查下,有情况再过来请教,谢谢您的回复。
页:
[1]