sunzbsd 发表于 2025-4-22 08:55:10

求教:32G12K128的EEPROM读写不可靠问题

各位大师,你们好:
      本人试用32G12K128,EEPROM的读、擦、写,参照了官网提供的代码:(STC32G-DEMO-CODE-V9.6)→(18-通过串口2发送命令读写EEPROM测试程序)→(C语言)→UART-EEPROM.c
      现在的问题是,读写出错率太高,一时不知如何解决,请教各位老师指点,谢谢。
      本人分别编写了三个函数:
      //EEPROM相关定义
#define EEPROMoperationAddress 0x0000                //定义EEPROM所在扇区及初始地址

各函数如下:

关闭IAP函数:
void IapIdle(void)
{
      IAP_CONTR = 0;          //关闭 IAP 功能
    IAP_CMD = 0;            //清除命令寄存器
    IAP_TRIG = 0;         //清除触发寄存器
    IAP_ADDRE = 0xff;       //将地址设置到非 IAP 区域
    IAP_ADDRH = 0xff;       //将地址设置到非 IAP 区域
    IAP_ADDRL = 0xff;
}

扇区擦除函数:
//读取EEPROM,获取量程、波特率、从机地址等数据
void EEPROMradDataByteFunction(ulong EEPROMaddress,uchar *dataAddress,uchar quantity)
{
      EA=0;      //关闭所有中断
      
      IAP_CONTR = 0x80; //使能 IAP
    IAP_TPS = mainFosc/1000000;      //设置等待参数22.1184MHz
    IAP_CMD = 1;//设置 IAP 读命令
      do
      {
                IAP_ADDRE = (uchar)(EEPROMaddress >> 16); //送地址高字节(地址需要改变时才需重新送地址)
      IAP_ADDRH = (uchar)(EEPROMaddress >> 8);//送地址中字节(地址需要改变时才需重新送地址)
      IAP_ADDRL = (uchar)EEPROMaddress;         //送地址低字节(地址需要改变时才需重新送地址)
      IAP_TRIG = 0x5a; //写触发命令(0x5a)
      IAP_TRIG = 0xa5; //写触发命令(0xa5)
      _nop_();   //由于STC32G是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
      _nop_();
                _nop_();
                _nop_();
                _nop_();
                *dataAddress = IAP_DATA; //读 IAP 数据
      EEPROMaddress++;
      dataAddress++;
      }while(--quantity);
      IapIdle();      //关闭IAP功能
      
      EA=1;      //打开所有中断
}

多字节读函数:
void EEPROMradDataByteFunction(ulong EEPROMaddress,uchar *dataAddress,uchar quantity)
{
      EA=0;      //关闭所有中断
      
      IAP_CONTR = 0x80; //使能 IAP
    IAP_TPS = mainFosc/1000000;      //设置等待参数22.1184MHz
    IAP_CMD = 1;//设置 IAP 读命令
      do
      {
                IAP_ADDRE = (uchar)(EEPROMaddress >> 16); //送地址高字节(地址需要改变时才需重新送地址)
      IAP_ADDRH = (uchar)(EEPROMaddress >> 8);//送地址中字节(地址需要改变时才需重新送地址)
      IAP_ADDRL = (uchar)EEPROMaddress;         //送地址低字节(地址需要改变时才需重新送地址)
      IAP_TRIG = 0x5a; //写触发命令(0x5a)
      IAP_TRIG = 0xa5; //写触发命令(0xa5)
      _nop_();   //由于STC32G是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
      _nop_();
                _nop_();
                _nop_();
                _nop_();
                *dataAddress = IAP_DATA; //读 IAP 数据
      EEPROMaddress++;
      dataAddress++;
      }while(--quantity);
      IapIdle();      //关闭IAP功能
      
      EA=1;      //打开所有中断
}

多字节写函数:
/*在写数据之前按照PDF推荐,先将EEPROM内的16个数据读出到EEPROMarray数组,然后擦除,最后再将EEPROM数组的数据写回EEPROM中,重新读取EEPROM的16个数据,存放到anotherArray数组中,以判断是否读写成功,出错概率很大*/
void EEPROMwriteAnyByte(ulong EEPROMaddress,uchar dataAddress[],uchar quantity)
{
      uchar i=0;
      EA=0;      //关闭所有中断
      
      IAP_CONTR = 0x80; //使能 IAP
    IAP_TPS = mainFosc/1000000;      //设置等待参数22.1184MHz
    IAP_CMD = 2;//设置 IAP 写命令
      do
      {
                IAP_ADDRE = (uchar)(EEPROMaddress >> 16); //送地址高字节(地址需要改变时才需重新送地址)
      IAP_ADDRH = (uchar)(EEPROMaddress >> 8);//送地址中字节(地址需要改变时才需重新送地址)
      IAP_ADDRL = (uchar)EEPROMaddress;         //送地址低字节(地址需要改变时才需重新送地址)
      //IAP_DATA = *dataAddress;         //写 IAP 数据
                IAP_DATA = dataAddress;         //写 IAP 数据
      IAP_TRIG = 0x5a; //写触发命令(0x5a)
      IAP_TRIG = 0xa5; //写触发命令(0xa5)
      _nop_();   //由于STC32G是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
      _nop_();
                _nop_();
                _nop_();
                _nop_();
      EEPROMaddress++;
      dataAddress++;
                i++;
      }while(--quantity);
      IapIdle();      //关闭IAP功能
      
      EA=1;      //打开所有中断
}

请指教
再次感谢

      

国芯人工智能 发表于 2025-4-22 08:58:00

在STC32G12K128的EEPROM读写过程中,出现高错误率的问题可能涉及多个方面。以下是一些可能的原因及解决方案,供您参考:

1. 时钟配置与等待时间
问题分析:EEPROM操作需要特定的时钟频率和等待时间。如果时钟配置不当或等待时间不足,可能导致读写操作失败。
解决方案:确保IAPTPS寄存器正确配置,以匹配主时钟频率。IAPTPS的计算公式为:IAPTPS = mainFosc / 1000000。例如,如果主时钟频率为12MHz,则IAPTPS应设置为12。此外,确保在EEPROM操作后留有足够的等待时间。

2. 地址对齐与边界检查
问题分析:EEPROM操作通常要求地址对齐,且不能跨越扇区边界。如果地址未对齐或操作跨越了扇区边界,可能导致读写错误。
解决方案:确保操作地址正确对齐,并检查操作范围是否在单个扇区内。例如,STC32G12K128的EEPROM扇区大小为512字节,确保操作地址和长度不跨越扇区边界。

3. 电源稳定性
问题分析:EEPROM操作对电源稳定性要求较高。如果电源波动较大,可能导致读写错误。
解决方案:确保电源稳定,避免在电源波动较大的情况下进行EEPROM操作。可以考虑增加电源滤波电容或使用稳压电源。

4. 中断干扰
问题分析:在EEPROM操作过程中,如果中断未被正确关闭,可能导致操作被中断,从而引发错误。
解决方案:在EEPROM操作前关闭所有中断(如您代码中的EA=0),并在操作完成后重新开启中断。

5. EEPROM寿命与磨损均衡
问题分析:EEPROM有有限的擦写次数,频繁的擦写操作可能导致某些扇区失效。
解决方案:尽量减少EEPROM的擦写次数,采用磨损均衡算法,将数据分散到不同的扇区中。

6. 代码优化与调试
问题分析:代码实现可能存在潜在问题,如未正确设置寄存器或操作顺序不当。
解决方案:仔细检查代码,确保所有寄存器设置正确,操作顺序符合数据手册要求。可以通过调试工具逐步检查每一步操作的结果。

7. 硬件连接与PCB设计
问题分析:硬件连接不良或PCB设计不当可能导致信号干扰,影响EEPROM操作。
解决方案:检查硬件连接,确保EEPROM相关引脚连接正确。优化PCB设计,减少信号干扰。

8. 固件版本与数据手册
问题分析:固件版本可能存在已知问题,或数据手册中的信息不准确。
解决方案:确保使用最新的固件版本,并参考最新的数据手册。如有必要,联系芯片厂商获取技术支持。

9. 环境因素
问题分析:极端温度或湿度可能影响EEPROM的可靠性。
解决方案:确保工作环境在芯片规定的温度范围内,避免在极端环境下进行EEPROM操作。

10. 测试与验证
问题分析:未进行充分的测试与验证,可能导致问题未被及时发现。
解决方案:编写全面的测试程序,覆盖各种可能的操作场景,确保EEPROM读写的可靠性。

示例代码优化
以下是对您提供的代码进行优化的示例:

c
// EEPROM相关定义
define EEPROMoperationAddress 0x0000 // 定义EEPROM所在扇区及初始地址

// 关闭IAP函数
void IapIdle(void)
{
    IAPCONTR = 0;          // 关闭 IAP 功能
    IAPCMD = 0;            // 清除命令寄存器
    IAPTRIG = 0;         // 清除触发寄存器
    IAPADDRE = 0xff;       // 将地址设置到非 IAP 区域
    IAPADDRH = 0xff;       // 将地址设置到非 IAP 区域
    IAPADDRL = 0xff;
}

// 扇区擦除函数
void EEPROMradDataByteFunction(ulong EEPROMaddress, uchar dataAddress, uchar quantity)
{
    EA = 0; // 关闭所有中断

    IAPCONTR = 0x80; // 使能 IAP
    IAPTPS = mainFosc / 1000000; // 设置等待参数

    // 确保地址对齐
    if (EEPROMaddress % 512 != 0) {
      // 处理地址未对齐的情况
      return;
    }

    // 执行EEPROM操作
    // ...

    IapIdle(); // 关闭IAP
    EA = 1; // 重新开启中断
}

总结
EEPROM读写不可靠问题可能由多种因素引起,包括时钟配置、地址对齐、电源稳定性、中断干扰等。通过仔细检查代码、优化硬件设计、确保电源稳定以及进行充分的测试,可以有效提高EEPROM读写的可靠性。如果问题仍然存在,建议联系芯片厂商获取进一步的技术支持。

希望以上建议对您有所帮助,祝您顺利解决问题!

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

DebugLab 发表于 2025-4-22 09:36:16

写之前要扇区擦除
页: [1]
查看完整版本: 求教:32G12K128的EEPROM读写不可靠问题