EEPROM写一个数据变成全扇区都同时这个数据,这是什么原因引起的?
环境:单片机: ai8h2k32u
频率: 24mhz
现象: 写数据时, 最后一次写的一个字节值会把全部扇区的值覆盖。
问题发现: 下单不久的这个芯片, 原来用stc8h1k28的项目读写eeprom没有问题, 但移植到这个芯片后,发现写数据区后,每个数据都变成最后一个写的数据了,很怪异。折腾一番,一直没有发现代码有明显的bug.最后采用了最小代码法,用串口输出,发现的确是这种现象。
发上来求助大佬们
上代码和运行结果图: D等高手来解答 看不懂{:4_166:} 496649247 发表于 2025-1-4 08:52
看不懂
只是一个简化了的测试程序
这个输出理论上是: FF FF FF 0A01 FF FF 0A 01 02 FF 0A 01 02 03 0A 没看到IAPREAD函数 void Iap_Idle(void)
{
IAP_CONTR&=~IAPEN;
IAP_CMD=IAP_IDL;
IAP_TRIG=0x00;
IAP_ADDRH=0x80;
IAP_ADDRL=0x00;
}unsigned char Iap_Read_Byte(unsigned char sector,unsigned int addr)
{
return *(CBYTE+IAP_OFFSET+sector*0x0200+addr);
}void Iap_Program_Byte(unsigned char sector,unsigned int addr,unsigned char dat)
{
unsigned int add;
add=sector*0x0200+addr;
IAP_CONTR|=IAPEN;
IAP_TPS=IAP_TPS_;
IAP_CMD=IAP_WRITE;
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_DATA=dat;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
_nop_();
Iap_Idle();
}void Iap_Erase_Sector(unsigned char sector)
{
unsigned int add;
add=sector*0x0200;
IAP_CONTR|=IAPEN;
IAP_TPS=IAP_TPS_;
IAP_CMD=IAP_ERASE;
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
_nop_();
Iap_Idle();
}
我采用的是例程库的的read和write,所以没有贴。 我也贴出来这几个方法。 等下我用版主的函数方法来测试一下。
void IapIdle()
{
IAP_CONTR = 0; //¹Ø±ÕIAP¹¦ÄÜ
IAP_CMD = 0; //Çå³ýÃüÁî¼Ä´æÆ÷
IAP_TRIG = 0; //Çå³ý´¥·¢¼Ä´æÆ÷
IAP_ADDRH = 0x80; //½«µØÖ·ÉèÖõ½·ÇIAPÇøÓò
IAP_ADDRL = 0;
}
char IapRead(int addr)
{
char dat;
IAP_CONTR = 0x80; //ʹÄÜIAP
IAP_TPS = TPS; //ÉèÖõȴý²ÎÊý12MHz
IAP_CMD = 1; //ÉèÖÃIAP¶ÁÃüÁî
IAP_ADDRL = addr; //ÉèÖÃIAPµÍµØÖ·
IAP_ADDRH = addr >> 8; //ÉèÖÃIAP¸ßµØÖ·
IAP_TRIG = 0x5a; //д´¥·¢ÃüÁî(0x5a)
IAP_TRIG = 0xa5; //д´¥·¢ÃüÁî(0xa5)
_nop_();
dat = IAP_DATA; //¶ÁIAPÊý¾Ý
IapIdle(); //¹Ø±ÕIAP¹¦ÄÜ
return dat;
}
void IapProgram(int addr, char dat)
{
IAP_CONTR = 0x80; //ʹÄÜIAP
IAP_TPS = TPS; //ÉèÖõȴý²ÎÊý12MHz
IAP_CMD = 2; //ÉèÖÃIAPдÃüÁî
IAP_ADDRL = addr; //ÉèÖÃIAPµÍµØÖ·
IAP_ADDRH = addr >> 8; //ÉèÖÃIAP¸ßµØÖ·
IAP_DATA = dat; //дIAPÊý¾Ý
IAP_TRIG = 0x5a; //д´¥·¢ÃüÁî(0x5a)
IAP_TRIG = 0xa5; //д´¥·¢ÃüÁî(0xa5)
_nop_();
IapIdle(); //¹Ø±ÕIAP¹¦ÄÜ
}
void IapErase(int addr)
{
IAP_CONTR = 0x80; //ʹÄÜIAP
IAP_TPS = TPS; //ÉèÖõȴý²ÎÊý12MHz
IAP_CMD = 3; //ÉèÖÃIAP²Á³ýÃüÁî
IAP_ADDRL = addr; //ÉèÖÃIAPµÍµØÖ·
IAP_ADDRH = addr >> 8; //ÉèÖÃIAP¸ßµØÖ·
IAP_TRIG = 0x5a; //д´¥·¢ÃüÁî(0x5a)
IAP_TRIG = 0xa5; //д´¥·¢ÃüÁî(0xa5)
_nop_(); //
IapIdle(); //¹Ø±ÕIAP¹¦ÄÜ
} DebugLab 发表于 2025-1-4 13:06
测试了代码,结果不是预想的。以下是我根据代码定义的一些值, 看有没有问题
注: CBYTE和IAP_OFFSET看会不会定义有问题? 地址初始值直接用扇区来转化了,所以这个offset我设定为0
这个打印的结果图
这是测试打印代码:
因为了编译通过, 改了几个宏。 干脆我把main.c发上来让大家排错 marchwang88 发表于 2025-1-4 14:28
测试了代码,结果不是预想的。以下是我根据代码定义的一些值, 看有没有问题
CBYTE是libc ABSACC.H中的定义,是一个指针,不是数值0,#include <absacc.h>即可
IAP_OFFSET是MOVC读的基地址,就是code区的大小
该型号为IAP,EEPROM大小可自定义
最大为0x8000
IAP_OFFSET=0x8000-用户设置的EEPROM大小x
所以应为
#define IAP_OFFSET (0x8000-x)
假设只使用1个扇区
就是
#define IAP_OFFSET (0x8000-0x0200)
页:
[1]
2