王锦平 发表于 2025-3-3 11:13:33

玄学的eeprom保存

<p>我写了个数据保存函数,用以保存ASCⅡ码,读与写却是不匹配。。。以下是我的代码</p>
<pre><code class="language-c">BYTE* eepRom_Read_DevAddr(void)
{
    unsigned char cnt;
    const unsigned char DevIdLen = EEPROM_DEVID_END_ADDR - EEPROM_DEVID_START_ADDR;
    memset(eepRomBuffer, 0, sizeof(eepRomBuffer));
    for ( cnt = 0; cnt &lt; DevIdLen; cnt++ )
      eepRomBuffer = IapReadByte(EEPROM_DEVID_START_ADDR + cnt);
    return eepRomBuffer;
}

int eepRom_Save_DeviceAddress(const char* DevId)
{
    unsigned char cnt = 0;
    BYTE Flag_QRcodeShow = 0;
    const int DevIdLen = EEPROM_DEVID_END_ADDR - EEPROM_DEVID_START_ADDR;
    if ( *(DevId + DevIdLen) != '\0' || DevId == NULL )
      return EEPROM_ERR_ARG; // 没有结束符或参数为NULL
    Flag_QRcodeShow = IapReadByte((WORD)EEPROM_QRCODE_FLAG_ADDR);// 先保存地址二维码显示否
    DebugPrint(TAG, &quot;frist, save QRcode flag: %bu&quot;, Flag_QRcodeShow);

//***********写入eeprom************
    if ( IapEraseSector(IAP_ADDRESS2) )
      goto _EEPROM_ERR;

    DebugPrint(TAG, &quot;erase successes... will write data: %s&quot;, DevId);
    Delay_100ms();
    for ( cnt = 0; cnt &lt; DevIdLen; cnt++ )
    {
      if ( IapProgramByte((EEPROM_DEVID_START_ADDR + cnt), (*(DevId + cnt))) )
      {
            DebugPrint(TAG, &quot;write eepRom error&quot;);
            goto _EEPROM_ERR;
      }
      Delay_10ms();
      DebugPrint(TAG, &quot;write byte: %bu, read: %bu&quot;, *(DevId + cnt), IapReadByte(EEPROM_DEVID_START_ADDR + cnt));
    }
    IapProgramByte((WORD)EEPROM_QRCODE_FLAG_ADDR, Flag_QRcodeShow);//保存地址二维码显示否
    DebugPrint(TAG, &quot;devId writting successes...&quot;);
    return (strcmp(DevId, eepRom_Read_DevAddr()) == 0) ? EEPROM_OK : EEPROM_FAIL;
_EEPROM_ERR:
    CLEAR_BIT(IAP_CONTR, 4); // 清除IAP错误
    return (int)IapEraseSector(IAP_ADDRESS2);
}


</code></pre>
<p>代码中,eeprom的读写是这样实现的( Soc设置的频率为33.1776MHz )</p>
<pre><code class="language-c">//********************关闭IAP*******************************ok
static void IapIdle()
{
    IAP_CONTR = 0;                  //关闭IAP功能
    IAP_CMD = 0;                  //清除命令寄存器
    IAP_TRIG = 0;                   //清除触发寄存器
    IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

//************************从ISP/IAP/EEPROM区域读取一字节****************************ok
static BYTE IapReadByte(WORD addr)
{
    BYTE dat;                     //数据缓冲区
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_TPS = iapTps; //设置等待参数 ********************************************STC8C2K64S2
    IAP_CMD = CMD_READ;             //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr &gt;&gt; 8;          //设置IAP高地址
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    dat = IAP_DATA;               //读ISP/IAP/EEPROM数据
    IapIdle();                      //关闭IAP功能
    return dat;                     //返回
}

//*********写一字节数据到ISP/IAP/EEPROM区域*************************************ok
static BYTE IapProgramByte(WORD addr, BYTE dat)
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_TPS = iapTps; //设置等待参数 ********************************************STC8C2K64S2
    IAP_CMD = CMD_PROGRAM;          //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr &gt;&gt; 8;          //设置IAP高地址
    IAP_DATA = dat;               //写ISP/IAP/EEPROM数据
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();                                                //关闭IAP功能
    return FIND_BIT(IAP_CONTR, 4);
}

//**************************************扇区擦除************************************ok
static BYTE IapEraseSector(WORD addr)
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_ERASE;            //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr &gt;&gt; 8;          //设置IAP高地址
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();                                                //关闭IAP功能
    return FIND_BIT(IAP_CONTR, 4);
}
</code></pre>
<p>按照正常来说,我那保存字符串到eeprom的函数应该是正常生效的。但实际上却出错了,打印了以下的log</p>
<pre><code class="language-text">:frist, save QRcode flag: 255
:erase successes... will write data: BCDE
:write byte: 66, read: 0
:write byte: 67, read: 1
:write byte: 68, read: 0
:write byte: 69, read: 65
:devId writting successes...
:save DevId status: fail
</code></pre>
<p>而我的另一个同样也是保存数据到eeprom的函数,读与写对比却是没有问题的</p>
<pre><code class="language-c">BYTE* eepRom_Read_Name(const int index)
{
    BYTE MaxCnt = 0, cnt = 0;
    memset(eepRomBuffer, 0, sizeof(eepRomBuffer));
    switch ( index )
    {
      case 1:
      {
            MaxCnt = IapReadByte(EEPROM_NAME1_CNT_ADDR);
            for ( cnt = 0; cnt &lt; MaxCnt; cnt++ )
            {
                eepRomBuffer = IapReadByte(EEPROM_NAME1STR_ADDR + cnt);
            }
      }break;
      case 2:
      {
            MaxCnt = IapReadByte(EEPROM_NAME2_CNT_ADDR);
            for ( cnt = 0; cnt &lt; MaxCnt; cnt++ )
            {
                eepRomBuffer = IapReadByte(EEPROM_NAME2STR_ADDR + cnt);
            }
      }break;
      case 3:
      {
            MaxCnt = IapReadByte(EEPROM_NAME3_CNT_ADDR);
            for ( cnt = 0; cnt &lt; MaxCnt; cnt++ )
            {
                eepRomBuffer = IapReadByte(EEPROM_NAME3STR_ADDR + cnt);
            }
      }break;
      case 4:
      {
            MaxCnt = IapReadByte(EEPROM_NAME4_CNT_ADDR);
            for ( cnt = 0; cnt &lt; MaxCnt; cnt++ )
            {
                eepRomBuffer = IapReadByte(EEPROM_NAME4STR_ADDR + cnt);
            }
      }break;
      default:
            DebugPrint(TAG, &quot;ReadName index fail&quot;);
            return NULL;
    }
    return eepRomBuffer;
}

BYTE eepRom_Read_NameLen(const int index)
{
    BYTE len = 0;
    switch ( index )
    {
      case 1:
            len = IapReadByte(EEPROM_NAME1_CNT_ADDR);
            break;
      case 2:
            len = IapReadByte(EEPROM_NAME2_CNT_ADDR);
            break;
      case 3:
            len = IapReadByte(EEPROM_NAME3_CNT_ADDR);
            break;
      case 4:
            len = IapReadByte(EEPROM_NAME4_CNT_ADDR);
            break;
      default:
            DebugPrint(TAG, &quot;ReadNameLen index fail&quot;);
            break;
    }
    return len;
}

int eepRom_Save_Name(const char* Name, const unsigned int len, const unsigned int index)
{
    unsigned int cnt = 0;
    const unsigned int MaxCnt = EEPROM_NAME_END_ADDR - EEPROM_NAME_START_ADDR;
    const unsigned char DataHead = EEPROM_NAME1STR_ADDR - EEPROM_NAME_START_ADDR;
    //BYTE tmpSave = {0};
    if ( Name == NULL || len == 0 )
      return EEPROM_ERR_ARG;

    memset(eepRomBuffer, 0, sizeof(eepRomBuffer));
    // 先读出数据
    for ( cnt = 0; cnt &lt; MaxCnt; cnt++ )
    {
      eepRomBuffer = IapReadByte(EEPROM_NAME_START_ADDR);
    }
    switch ( index )
    {
      case 1:
      {
            eepRomBuffer = len;
            memcpy(eepRomBuffer + DataHead, Name, len);
      }break;
      case 2:
      {
            eepRomBuffer = len;
            memcpy(eepRomBuffer + DataHead + (EEPROM_NAME_MAX_LEN * 1), Name, len);
      }break;
      case 3:
      {
            eepRomBuffer = len;
            memcpy(eepRomBuffer + DataHead + (EEPROM_NAME_MAX_LEN * 2), Name, len);
      }break;
      case 4:
      {
            eepRomBuffer = len;
            memcpy(eepRomBuffer + DataHead + (EEPROM_NAME_MAX_LEN * 3), Name, len);
      }break;
      default:
            DebugPrint(TAG, &quot;SaveName index fail&quot;);
            return EEPROM_ERR_ARG;
    }
    if ( IapEraseSector(EEPROM_NAME_START_ADDR) )
      goto _EEPROM_ERROR;
    for ( cnt = 0; cnt &lt; MaxCnt; cnt++ )
    {
      if ( IapProgramByte(EEPROM_NAME_START_ADDR + cnt, eepRomBuffer) )
            goto _EEPROM_ERROR;
    }
    DebugPrint(TAG, &quot;SaveName successes&quot;);
    return (memcmp(eepRom_Read_Name(index), Name, len) == 0) ? EEPROM_OK : EEPROM_FAIL;

_EEPROM_ERROR:
    DebugPrint(TAG, &quot;erase or write error&quot;);
    return IapEraseSector(EEPROM_NAME_START_ADDR);
}
</code></pre>
<pre><code class="language-text">:SaveName successes
:1-Save name status: ok
:Show string
:parse fail
:2-Display GB2312 status: FAIL, cnt: 0
:parse fail
:2-Display GB2312 status: FAIL, cnt: 0
:parse status: ok
:recv data ok
</code></pre>
<p>这么看起来,两个函数的保存与读取其实并没有什么区别。但函数 <code>eepRom_Save_DeviceAddress()</code>就是返回了错误值。希望大佬能指导我该如何分析🙏🙏🙏</p>

国芯人工智能 发表于 2025-3-3 11:18:00

根据您的描述,EEPROM读写的ASCII码数据不匹配,可能涉及以下几个问题:首先,检查EEPROM的起始地址和结束地址是否正确,确保读写范围一致。其次,确认`eepRomBuffer`的大小是否足够存储读取的数据,避免溢出或截断。此外,EEPROM的读写时序和延迟可能影响数据一致性,建议在读写操作后增加适当的延时或检查EEPROM的状态寄存器。最后,确保硬件连接稳定,避免因信号干扰导致数据错误。建议逐步调试,验证每个环节的正确性,以定位问题根源。

[本文内容由国芯人工智能辅助生成,仅供参考]

国芯人工智能 发表于 2025-3-3 11:23:00

在您的代码中,可能存在以下问题导致EEPROM读取与写入的ASCII码不匹配:

1. **地址范围确认**:确保`EEPROM_DEVID_START_ADDR`和`EEPROM_DEVID_END_ADDR`定义正确,且不会超出EEPROM的物理地址范围。

2. **缓冲区大小**:`eepRomBuffer`的大小应至少为`DevIdLen`,以确保能存储所有读取的数据。

3. **读取函数实现**:确认EEPROM读取函数是否正确实现,每次读取一个字节并存入`eepRomBuffer`。

4. **写入函数检查**:检查写入函数是否正确将ASCII码写入EEPROM,确保写入的数据与预期一致。

5. **数据校验**:建议在写入后立即读取并进行校验,以确保数据一致性。

建议您逐步排查上述问题,必要时增加调试信息,以便定位具体原因。

[本文内容由国芯人工智能辅助生成,仅供参考]

王锦平 发表于 2025-3-3 11:30:06

<p>我尝试上电就对eeprom进行写入,首次写入成功,但后面的写入都没有成功</p>
<pre><code class="language-text">:UART buffer memory reset
:frist, save QRcode flag: 255
:erase successes... will write data: 010A
:write byte: 48, read: 48
:write byte: 49, read: 49
:write byte: 48, read: 48
:write byte: 65, read: 65
:devId writting successes...
:save address ok
:frist, save QRcode flag: 255
:erase successes... will write data: 9999
:write byte: 57, read: 48
:write byte: 57, read: 49
:write byte: 57, read: 48
:write byte: 57, read: 1
:devId writting successes...
:save address fail
:frist, save QRcode flag: 255
:erase successes... will write data: 010A
:write byte: 48, read: 48
:write byte: 49, read: 49
:write byte: 48, read: 48
:write byte: 65, read: 1
:devId writting successes...
:save address fail
</code></pre>
<p>我在写入eeprom前也是有擦除的,但是写不进去寄存器也没有返回错误值</p>

DebugLab 发表于 2025-3-3 11:46:28





操作EEPROM之前关闭中断试试

王锦平 发表于 2025-3-3 11:49:29

国芯人工智能 发表于 2025-3-3 11:23
在您的代码中,可能存在以下问题导致EEPROM读取与写入的ASCII码不匹配:

1. **地址范围确认**:确保`EEPRO ...

1234都正常,到了第5步的时候就有问题了。请分析

王锦平 发表于 2025-3-3 11:52:22

DebugLab 发表于 2025-3-3 11:46
操作EEPROM之前关闭中断试试

大意了,没关中断

DebugLab 发表于 2025-3-3 11:58:56

王锦平 发表于 2025-3-3 11:52
大意了,没关中断

主程序和中断中都操作EEPROM才需要关中断避免重入问题

王锦平 发表于 2025-3-3 11:59:03

DebugLab 发表于 2025-3-3 11:46
操作EEPROM之前关闭中断试试

<h3>刚刚为IAP函数添加了中断</h3>
<pre><code class="language-c">//********************关闭IAP*******************************ok
static void IapIdle()
{
    IAP_CONTR = 0;                  //关闭IAP功能
    IAP_CMD = 0;                  //清除命令寄存器
    IAP_TRIG = 0;                   //清除触发寄存器
    IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

//************************从ISP/IAP/EEPROM区域读取一字节****************************ok
static BYTE IapReadByte(WORD addr)
{
    BYTE dat;                     //数据缓冲区
    GLOBAL_INTERRUPT(DISABLE);
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_TPS = iapTps; //设置等待参数 ********************************************STC8C2K64S2
    IAP_CMD = CMD_READ;             //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr &gt;&gt; 8;          //设置IAP高地址
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    dat = IAP_DATA;               //读ISP/IAP/EEPROM数据
    IapIdle();                      //关闭IAP功能
    GLOBAL_INTERRUPT(ENABLE);
    return dat;                     //返回
}

//*********写一字节数据到ISP/IAP/EEPROM区域*************************************ok
static BYTE IapProgramByte(WORD addr, BYTE dat)
{
    GLOBAL_INTERRUPT(DISABLE);
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_TPS = iapTps; //设置等待参数 ********************************************STC8C2K64S2
    IAP_CMD = CMD_PROGRAM;          //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr &gt;&gt; 8;          //设置IAP高地址
    IAP_DATA = dat;               //写ISP/IAP/EEPROM数据
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();                                                //关闭IAP功能
    GLOBAL_INTERRUPT(ENABLE);
    return FIND_BIT(IAP_CONTR, 4);
}

//**************************************扇区擦除************************************ok
static BYTE IapEraseSector(WORD addr)
{
    GLOBAL_INTERRUPT(DISABLE);
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_ERASE;            //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr &gt;&gt; 8;          //设置IAP高地址
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();                                                //关闭IAP功能
    GLOBAL_INTERRUPT(ENABLE);
    return FIND_BIT(IAP_CONTR, 4);
}
</code></pre>
<p>不过没有效果。。。</p>
<pre><code class="language-text">:UART buffer memory reset
:frist, save QRcode flag: 255
:erase successes... will write data: 010A
:write byte: 48, read: 48, addr: 0
:write byte: 49, read: 49, addr: 1
:write byte: 48, read: 48, addr: 2
:write byte: 65, read: 65, addr: 3
:devId writting successes...
:save address ok
:frist, save QRcode flag: 255
:erase successes... will write data: 9999
:write byte: 57, read: 48, addr: 0
:write byte: 57, read: 49, addr: 1
:write byte: 57, read: 48, addr: 2
:write byte: 57, read: 1, addr: 3
:devId writting successes...
:save address fail
:frist, save QRcode flag: 255
:erase successes... will write data: 010A
:write byte: 48, read: 48, addr: 0
:write byte: 49, read: 49, addr: 1
:write byte: 48, read: 48, addr: 2
:write byte: 65, read: 1, addr: 3
:devId writting successes...
:save address fail
</code></pre>
<p>如果只是关闭中断就可以的话,那么从一开始就不应该写入成功才对🤔</p>

ercircle 发表于 2025-3-3 12:39:46

这里写之前擦的地址正确吗?建议贴完整可复现的工程上来方便大家帮你分析


页: [1] 2
查看完整版本: 玄学的eeprom保存