漏风大衣 发表于 2023-3-3 17:15:22

求关于EEPROM的地址解惑



请问为什么stc片内EEPROM关闭操作的时候,示例上IAP_ADDR为什么设置成8000h啊?注释写着设置成非IAP区域,我查扇区地址这个位置不还是EEPROM的地址吗

神农鼎 发表于 2023-3-3 18:58:14



有些芯片8000H后已是无效地址,主要是要关闭 IAP允许位,这样就不会误擦除

LFB 发表于 2023-3-4 09:42:09

搭车问下,STC8H3K64S2,EEPROM功能可以仿真不?

神农鼎 发表于 2023-3-4 09:53:02

可以仿真EEPROM

LFB 发表于 2023-3-4 14:01:20

本帖最后由 LFB 于 2023-3-17 12:08 编辑

MCU型号 STC8H3K64S2 设置用户EEPROM大小为1K




//sfr IAP_CMD   = 0xC5;
#define IAP_STANDBY()   IAP_CMD = 0   //IAP空闲命令(禁止)
#define IAP_READ()      IAP_CMD = 1   //IAP读出命令
#define IAP_WRITE()   IAP_CMD = 2   //IAP写入命令
#define IAP_ERASE()   IAP_CMD = 3   //IAP擦除命令

//sfr IAP_TRIG= 0xC6;
#define IAP_TRIG()do{ IAP_TRIG = 0x5A,    IAP_TRIG = 0xA5 } while(0)   // IAP触发命令

//                                    7    6    5      4    3   21   0   Reset Value
//sfr IAP_CONTR = 0xC7;   IAPEN SWBS SWRST CFAIL-   --   -   0000,x000    //IAP Control Register

#define IAP_EN            (1<<7)
#define IAP_SWBS            (1<<6)
#define IAP_SWRST         (1<<5)
#define IAP_CMD_FAIL      (1<<4)

#define IAP_ENABLE()      do{ IAP_CONTR = IAP_EN; IAP_TPS = MAIN_Fosc / 1000000; } while(0)
#define IAP_DISABLE()       do{ IAP_CONTR = 0; IAP_CMD = 0; IAP_TRIG = 0; IAP_ADDRH = 0xff; IAP_ADDRL = 0xff; } while(0)

void F_EEPROM_Test(void)
{
    u16 EE_address = 0xFC00; <span style="color: rgb(255, 0, 0);">// 其实用IAP访问需从0000h开始(编辑增加说明)</span>
    u8 WrDataBuf = {0x55,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
    u8 RdDataBuf = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    u16 number;
    EA = 0;   //禁止中断

    // 先擦除
    IAP_ENABLE();         //设置等待时间,允许IAP操作,送一次就够
    IAP_ERASE();                        //宏调用, 送扇区擦除命令,命令不需改变时,不需重新送命令
                                        //只有扇区擦除,没有字节擦除,512字节/扇区。
                                        //扇区中任意一个字节地址都是扇区地址。
    IAP_ADDRH = (EE_address) / 256;       //送扇区地址高字节(地址需要改变时才需重新送地址)
    IAP_ADDRL = (EE_address) % 256;       //送扇区地址低字节
    //触发EEPROM操作
    IAP_TRIG = 0x5a; //写触发命令(0x5a)
    IAP_TRIG = 0xa5; //写触发命令(0xa5)
    _nop_();

    // 写
    IAP_ENABLE();         //设置等待时间,允许IAP操作,送一次就够
    IAP_WRITE();                        //宏调用, 送扇区擦除命令,命令不需改变时,不需重新送命令
    for (number = 0; number < 9; ++number)
    {
                                          //只有扇区擦除,没有字节擦除,512字节/扇区。
                                          //扇区中任意一个字节地址都是扇区地址。
      IAP_ADDRH = (EE_address) / 256;       //送扇区地址高字节(地址需要改变时才需重新送地址)
      IAP_ADDRL = (EE_address) % 256;       //送扇区地址低字节
      IAP_DATA = WrDataBuf;

      //触发EEPROM操作
      IAP_TRIG = 0x5a; //写触发命令(0x5a)
      IAP_TRIG = 0xa5; //写触发命令(0xa5)
      _nop_();
      EE_address++;
    }


    EE_address = 0xFC00;         <font color="#ff0000">// 其实用IAP访问需从0000h开始(编辑增加说明)</font>
    IAP_ENABLE();         //设置等待时间,允许IAP操作,送一次就够
    IAP_READ();             //送字节读命令,命令不需改变时,不需重新送命令
    for (number = 0; number < 9; ++number)
    {
      IAP_ADDRH = EE_address / 256; //设置 IAP 地址高字节
      IAP_ADDRL = EE_address % 256; //设置 IAP 地址低字节
      IAP_TRIG = 0x5a; //写触发命令(0x5a)
      IAP_TRIG = 0xa5; //写触发命令(0xa5)
      _nop_();
      _nop_();
      RdDataBuf = IAP_DATA; //读 IAP 数据
      EE_address++;
    }

    // 判断写入与读出数据是否相同
    for (number = 0; number < 9; ++number)
    {
      if(RdDataBuf != WrDataBuf)
      {
            break;
      }
    }

    if(number < 9)
    {
      P55 = 0;
      _nop_();    // 不同 仿真运行时跳到此处
    }
    else
    {
      P55 = 1;
      _nop_();    // 相同
    }
    EA = 1;   //使能中断
}

能不能帮看看是哪的问题?谢谢.

页: [1]
查看完整版本: 求关于EEPROM的地址解惑