marchwang88 发表于 2025-1-4 01:26:45

EEPROM写一个数据变成全扇区都同时这个数据,这是什么原因引起的?

环境:
      单片机: ai8h2k32u
      频率:   24mhz

现象: 写数据时, 最后一次写的一个字节值会把全部扇区的值覆盖。


问题发现: 下单不久的这个芯片, 原来用stc8h1k28的项目读写eeprom没有问题, 但移植到这个芯片后,发现写数据区后,每个数据都变成最后一个写的数据了,很怪异。折腾一番,一直没有发现代码有明显的bug.最后采用了最小代码法,用串口输出,发现的确是这种现象。
发上来求助大佬们

上代码和运行结果图:

wangxiangtan 发表于 2025-1-4 08:48:04

D等高手来解答

496649247 发表于 2025-1-4 08:52:00

看不懂{:4_166:}

marchwang88 发表于 2025-1-4 10:33:52

496649247 发表于 2025-1-4 08:52
看不懂

只是一个简化了的测试程序
这个输出理论上是: FF FF FF 0A01 FF FF 0A 01 02 FF 0A 01 02 03 0A

DebugLab 发表于 2025-1-4 13:04:05

没看到IAPREAD函数

DebugLab 发表于 2025-1-4 13:06:54

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();
}

marchwang88 发表于 2025-1-4 13:15:14

我采用的是例程库的的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¹¦ÄÜ
}

marchwang88 发表于 2025-1-4 14:28:33

DebugLab 发表于 2025-1-4 13:06


测试了代码,结果不是预想的。以下是我根据代码定义的一些值, 看有没有问题


注: CBYTE和IAP_OFFSET看会不会定义有问题? 地址初始值直接用扇区来转化了,所以这个offset我设定为0

这个打印的结果图



这是测试打印代码:

marchwang88 发表于 2025-1-4 14:37:52

因为了编译通过, 改了几个宏。 干脆我把main.c发上来让大家排错

DebugLab 发表于 2025-1-5 10:25:20

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
查看完整版本: EEPROM写一个数据变成全扇区都同时这个数据,这是什么原因引起的?