找回密码
 立即注册
查看: 434|回复: 13

玄学的eeprom保存

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-04-14 00:31:51
已绑定手机

5

主题

43

回帖

355

积分

中级会员

积分
355
发表于 2025-3-3 11:13:33 | 显示全部楼层 |阅读模式

我写了个数据保存函数,用以保存ASCⅡ码,读与写却是不匹配。。。以下是我的代码

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 < DevIdLen; cnt++ )
        eepRomBuffer[cnt] = 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, "frist, save QRcode flag: %bu", Flag_QRcodeShow);

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

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


代码中,eeprom的读写是这样实现的( Soc设置的频率为33.1776MHz )

//********************关闭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 >> 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 >> 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 >> 8;          //设置IAP高地址
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();						//关闭IAP功能
    return FIND_BIT(IAP_CONTR, 4);
}

按照正常来说,我那保存字符串到eeprom的函数应该是正常生效的。但实际上却出错了,打印了以下的log

[eepRom]:frist, save QRcode flag: 255
[eepRom]:erase successes... will write data: BCDE
[eepRom]:write byte: 66, read: 0
[eepRom]:write byte: 67, read: 1
[eepRom]:write byte: 68, read: 0
[eepRom]:write byte: 69, read: 65
[eepRom]:devId writting successes...
[protocol]:save DevId status: fail

而我的另一个同样也是保存数据到eeprom的函数,读与写对比却是没有问题的

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 < MaxCnt; cnt++ )
            {
                eepRomBuffer[cnt] = IapReadByte(EEPROM_NAME1STR_ADDR + cnt);
            }
        }break;
        case 2:
        {
            MaxCnt = IapReadByte(EEPROM_NAME2_CNT_ADDR);
            for ( cnt = 0; cnt < MaxCnt; cnt++ )
            {
                eepRomBuffer[cnt] = IapReadByte(EEPROM_NAME2STR_ADDR + cnt);
            }
        }break;
        case 3:
        {
            MaxCnt = IapReadByte(EEPROM_NAME3_CNT_ADDR);
            for ( cnt = 0; cnt < MaxCnt; cnt++ )
            {
                eepRomBuffer[cnt] = IapReadByte(EEPROM_NAME3STR_ADDR + cnt);
            }
        }break;
        case 4:
        {
            MaxCnt = IapReadByte(EEPROM_NAME4_CNT_ADDR);
            for ( cnt = 0; cnt < MaxCnt; cnt++ )
            {
                eepRomBuffer[cnt] = IapReadByte(EEPROM_NAME4STR_ADDR + cnt);
            }
        }break;
        default:
            DebugPrint(TAG, "ReadName index fail");
            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, "ReadNameLen index fail");
            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[EEPROM_NAME_MAX_LEN] = {0};
    if ( Name == NULL || len == 0 )
        return EEPROM_ERR_ARG;

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

_EEPROM_ERROR:
    DebugPrint(TAG, "erase or write error");
    return IapEraseSector(EEPROM_NAME_START_ADDR);
}
[eepRom]:SaveName successes
[protocol]:1-Save name status: ok
[protocol]:Show string
[FrontLib]:parse fail
[protocol]:2-Display GB2312 status: FAIL, cnt: 0
[FrontLib]:parse fail
[protocol]:2-Display GB2312 status: FAIL, cnt: 0
[BT_Model]:parse status: ok
[main]:recv data ok

这么看起来,两个函数的保存与读取其实并没有什么区别。但函数 eepRom_Save_DeviceAddress()就是返回了错误值。希望大佬能指导我该如何分析🙏🙏🙏

回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

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

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 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. **数据校验**:建议在写入后立即读取并进行校验,以确保数据一致性。

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

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-04-14 00:31:51
已绑定手机

5

主题

43

回帖

355

积分

中级会员

积分
355
发表于 2025-3-3 11:30:06 | 显示全部楼层

我尝试上电就对eeprom进行写入,首次写入成功,但后面的写入都没有成功

[main]:UART buffer memory reset
[eepRom]:frist, save QRcode flag: 255
[eepRom]:erase successes... will write data: 010A
[eepRom]:write byte: 48, read: 48
[eepRom]:write byte: 49, read: 49
[eepRom]:write byte: 48, read: 48
[eepRom]:write byte: 65, read: 65
[eepRom]:devId writting successes...
[main]:save address ok
[eepRom]:frist, save QRcode flag: 255
[eepRom]:erase successes... will write data: 9999
[eepRom]:write byte: 57, read: 48
[eepRom]:write byte: 57, read: 49
[eepRom]:write byte: 57, read: 48
[eepRom]:write byte: 57, read: 1
[eepRom]:devId writting successes...
[main]:save address fail
[eepRom]:frist, save QRcode flag: 255
[eepRom]:erase successes... will write data: 010A
[eepRom]:write byte: 48, read: 48
[eepRom]:write byte: 49, read: 49
[eepRom]:write byte: 48, read: 48
[eepRom]:write byte: 65, read: 1
[eepRom]:devId writting successes...
[main]:save address fail

我在写入eeprom前也是有擦除的,但是写不进去寄存器也没有返回错误值

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-3-3 11:46:28 | 显示全部楼层
截图202503031145125877.jpg

截图202503031145447699.jpg

操作EEPROM之前关闭中断试试
DebugLab
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-04-14 00:31:51
已绑定手机

5

主题

43

回帖

355

积分

中级会员

积分
355
发表于 2025-3-3 11:49:29 | 显示全部楼层
国芯人*** 发表于 2025-3-3 11:23
在您的代码中,可能存在以下问题导致EEPROM读取与写入的ASCII码不匹配:

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

1234都正常,到了第5步的时候就有问题了。请分析
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-04-14 00:31:51
已绑定手机

5

主题

43

回帖

355

积分

中级会员

积分
355
发表于 2025-3-3 11:52:22 | 显示全部楼层
Debu*** 发表于 2025-3-3 11:46
操作EEPROM之前关闭中断试试

大意了,没关中断

点评

主程序和中断中都操作EEPROM才需要关中断避免重入问题  详情 回复 发表于 2025-3-3 11:58
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-3-3 11:58:56 | 显示全部楼层
王*** 发表于 2025-3-3 11:52
大意了,没关中断

主程序和中断中都操作EEPROM才需要关中断避免重入问题
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-04-14 00:31:51
已绑定手机

5

主题

43

回帖

355

积分

中级会员

积分
355
发表于 2025-3-3 11:59:03 | 显示全部楼层
[quote][size=2][url=forum.php?mod=redirect&goto=findpost&pid=149126&ptid=15405][color=#999999]DebugLab 发表于 2025-3-3 11:46[/color][/url][/size] 操作EEPROM之前关闭中断试试[/quote]

刚刚为IAP函数添加了中断

//********************关闭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 >> 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 >> 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 >> 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);
}

不过没有效果。。。

[main]:UART buffer memory reset
[eepRom]:frist, save QRcode flag: 255
[eepRom]:erase successes... will write data: 010A
[eepRom]:write byte: 48, read: 48, addr: 0
[eepRom]:write byte: 49, read: 49, addr: 1
[eepRom]:write byte: 48, read: 48, addr: 2
[eepRom]:write byte: 65, read: 65, addr: 3
[eepRom]:devId writting successes...
[main]:save address ok
[eepRom]:frist, save QRcode flag: 255
[eepRom]:erase successes... will write data: 9999
[eepRom]:write byte: 57, read: 48, addr: 0
[eepRom]:write byte: 57, read: 49, addr: 1
[eepRom]:write byte: 57, read: 48, addr: 2
[eepRom]:write byte: 57, read: 1, addr: 3
[eepRom]:devId writting successes...
[main]:save address fail
[eepRom]:frist, save QRcode flag: 255
[eepRom]:erase successes... will write data: 010A
[eepRom]:write byte: 48, read: 48, addr: 0
[eepRom]:write byte: 49, read: 49, addr: 1
[eepRom]:write byte: 48, read: 48, addr: 2
[eepRom]:write byte: 65, read: 1, addr: 3
[eepRom]:devId writting successes...
[main]:save address fail

如果只是关闭中断就可以的话,那么从一开始就不应该写入成功才对🤔

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2938

积分

荣誉版主

无情的代码机器

积分
2938
发表于 2025-3-3 12:39:46 | 显示全部楼层
这里写之前擦的地址正确吗?建议贴完整可复现的工程上来方便大家帮你分析

截图202503031238178629.jpg
截图202503031239439593.jpg
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 00:24 , Processed in 0.144675 second(s), 115 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表