找回密码
 立即注册
查看: 406|回复: 18

求助!

[复制链接]
  • 打卡等级:偶尔看看II
  • 打卡总天数:21
  • 最近打卡:2025-06-03 09:09:20
已绑定手机

9

主题

61

回帖

313

积分

中级会员

积分
313
发表于 2025-3-6 10:06:58 | 显示全部楼层 |阅读模式


程序如图,创造两个数组,一个数组保存到EEPROM里面,然后读取出来。但是效果如图,只会把最后一个内容保存到EEPROM里面,不知道啥问题。求指点
截图202503061003517183.jpg 截图202503061006199384.jpg

回复

使用道具 举报 送花

3

主题

711

回帖

133

积分

等待验证会员

积分
133
发表于 2025-3-6 10:08:00 | 显示全部楼层
根据您描述的问题,可能是由于EEPROM写入时未正确更新地址,导致每次写入都覆盖了同一位置。建议检查以下几点:

1. **地址管理**:确保每次写入EEPROM时,地址指针正确递增。例如,使用`EEPROM.write(address, value)`后,需更新`address`为`address + sizeof(value)`。

2. **写入循环**:确认写入操作在循环中正确执行。例如:
  
  1. cpp
  2.    for (int i = 0; i < arraySize; i++) {
  3.        EEPROM.write(address + i, array[i]);
  4.    }
复制代码

3. **读取验证**:读取时使用相同的地址逻辑,确保数据一致性。

4. **EEPROM寿命**:频繁写入可能影响EEPROM寿命,建议优化写入策略。

如果问题仍未解决,请提供更详细的代码片段,以便进一步分析。

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

使用道具 举报 送花

3

主题

711

回帖

133

积分

等待验证会员

积分
133
发表于 2025-3-6 10:08:00 | 显示全部楼层
根据您描述的问题,可能是由于在保存数组到EEPROM时,未正确设置地址偏移量,导致每次写入都覆盖了之前的数据。建议在写入EEPROM时,使用循环结构,并确保每次写入后地址递增。以下是示例代码片段:
  1. cpp
  2. for(int i = 0; i < arraySize; i++) {
  3.     EEPROM.write(addressOffset + i, array[i]);
  4. }
复制代码

读取时同样需要循环:
  1. cpp
  2. for(int i = 0; i < arraySize; i++) {
  3.     array[i] = EEPROM.read(addressOffset + i);
  4. }
复制代码

确保`addressOffset`正确设置,避免数据重叠。如果问题依旧,建议检查EEPROM的写入和读取操作是否正常,以及数组大小和EEPROM容量是否匹配。

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

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:21
  • 最近打卡:2025-06-03 09:09:20
已绑定手机

9

主题

61

回帖

313

积分

中级会员

积分
313
发表于 2025-3-6 10:18:20 | 显示全部楼层
  1. void task2(void)
  2. {
  3.     u8 buf10[10]={1,2,3,4,5,6,7,8,9,2};               
  4.     u8 buf1[10];
  5.     u8 i;
  6.     EEPROM_SectorErase(0xFC00);
  7.     EEPROM_write_n(0xFC00,buf10,10);
  8.     EEPROM_read_n(0xFC00,buf1,10);
  9.     printf("addr0:");
  10.     for(i=0;i<10;i++){
  11.         printf("%02x ",buf1[i]);
  12.     }
  13. }
复制代码
补:代码在此
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:462
  • 最近打卡:2025-06-16 10:02:39

33

主题

2447

回帖

5170

积分

论坛元老

积分
5170
发表于 2025-3-6 10:30:39 | 显示全部楼层

至少把读n 写n的代码也贴出来把,,,

还有就是32位模式下,,这样写的printf需要把u8的数组强转成16位么?



妈耶,,你这里设置的EEPROM区只有1K,,而且擦除能用物理地址么?只能用IAP地址把,,是不是你地址用错了
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:462
  • 最近打卡:2025-06-16 10:02:39

33

主题

2447

回帖

5170

积分

论坛元老

积分
5170
发表于 2025-3-6 10:36:01 | 显示全部楼层
还有一件事,,这个AI又开始智障了
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:21
  • 最近打卡:2025-06-03 09:09:20
已绑定手机

9

主题

61

回帖

313

积分

中级会员

积分
313
发表于 2025-3-6 10:50:14 | 显示全部楼层
_奶*** 发表于 2025-3-6 10:30
至少把读n 写n的代码也贴出来把,,,

还有就是32位模式下,,这样写的printf需要把u8的数组强转成16位么 ...

读写用的官方库函数,我贴下面了
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:21
  • 最近打卡:2025-06-03 09:09:20
已绑定手机

9

主题

61

回帖

313

积分

中级会员

积分
313
发表于 2025-3-6 10:51:07 | 显示全部楼层
  1. /*---------------------------------------------------------------------*/
  2. /* --- Web: www.STCAI.com ---------------------------------------------*/
  3. /*---------------------------------------------------------------------*/
  4. #include "AI8051U_EEPROM.h"
  5. //========================================================================
  6. // 函数: void ISP_Disable(void)
  7. // 描述: 禁止访问ISP/IAP.
  8. // 参数: non.
  9. // 返回: non.
  10. // 版本: V1.0, 2012-10-22
  11. //========================================================================
  12. void DisableEEPROM(void)
  13. {
  14.         IAP_CONTR = 0;                //禁止IAP操作
  15.         IAP_CMD   = 0;                //去除IAP命令
  16.         IAP_TRIG  = 0;                //防止IAP命令误触发
  17.         IAP_ADDRE = 0xff;   //将地址设置到非 IAP 区域
  18.         IAP_ADDRH = 0xff;   //将地址设置到非 IAP 区域
  19.         IAP_ADDRL = 0xff;
  20. }
  21. //========================================================================
  22. // 函数: void EEPROM_Trig(void)
  23. // 描述: 触发EEPROM操作.
  24. // 参数: none.
  25. // 返回: none.
  26. // 版本: V1.0, 2014-6-30
  27. //========================================================================
  28. void EEPROM_Trig(void)
  29. {
  30.         F0 = EA;    //保存全局中断
  31.         EA = 0;     //禁止中断, 避免触发命令无效
  32.         IAP_TRIG = 0x5A;
  33.         IAP_TRIG = 0xA5;                    //先送5AH,再送A5H到IAP触发寄存器,每次都需要如此
  34.                                                                                                                                                         //送完A5H后,IAP命令立即被触发启动
  35.                                                                                                                                                         //CPU等待IAP完成后,才会继续执行程序。
  36.         _nop_();   //由于AI8051U是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
  37.         _nop_();
  38.         _nop_();
  39.         _nop_();
  40.         EA = F0;    //恢复全局中断
  41. }
  42. //========================================================================
  43. // 函数: void EEPROM_read_n(u32 EE_address,u8 *DataAddress,u16 number)
  44. // 描述: 从指定EEPROM首地址读出n个字节放指定的缓冲.
  45. // 参数: EE_address:  读出EEPROM的首地址.
  46. //       DataAddress: 读出数据放缓冲的首地址.
  47. //       number:      读出的字节长度.
  48. // 返回: non.
  49. // 版本: V1.0, 2012-10-22
  50. //========================================================================
  51. void EEPROM_read_n(u32 EE_address,u8 *DataAddress,u16 number)
  52. {
  53.         IAP_ENABLE();                           //设置等待时间,允许IAP操作,送一次就够
  54.         IAP_READ();                             //送字节读命令,命令不需改变时,不需重新送命令
  55.         do
  56.         {
  57.                 IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
  58.                 IAP_ADDRH = (u8)(EE_address >> 8);  //送地址中字节(地址需要改变时才需重新送地址)
  59.                 IAP_ADDRL = (u8)EE_address;         //送地址低字节(地址需要改变时才需重新送地址)
  60.                 EEPROM_Trig();                      //触发EEPROM操作
  61.                 *DataAddress = IAP_DATA;            //读出的数据送往
  62.                 EE_address++;
  63.                 DataAddress++;
  64.         }while(--number);
  65.         DisableEEPROM();
  66. }
  67. //========================================================================
  68. // 函数: void EEPROM_SectorErase(u32 EE_address)
  69. // 描述: 把指定地址的EEPROM扇区擦除.
  70. // 参数: EE_address:  要擦除的扇区EEPROM的地址.
  71. // 返回: non.
  72. // 版本: V1.0, 2013-5-10
  73. //========================================================================
  74. void EEPROM_SectorErase(u32 EE_address)
  75. {
  76.         IAP_ENABLE();                       //设置等待时间,允许IAP操作,送一次就够
  77.         IAP_ERASE();                        //宏调用, 送扇区擦除命令,命令不需改变时,不需重新送命令
  78.                                                                                                                                                         //只有扇区擦除,没有字节擦除,512字节/扇区。
  79.                                                                                                                                                         //扇区中任意一个字节地址都是扇区地址。
  80.         IAP_ADDRE = (u8)(EE_address >> 16); //送扇区地址高字节(地址需要改变时才需重新送地址)
  81.         IAP_ADDRH = (u8)(EE_address >> 8);  //送扇区地址中字节(地址需要改变时才需重新送地址)
  82.         IAP_ADDRL = (u8)EE_address;         //送扇区地址低字节(地址需要改变时才需重新送地址)
  83.         EEPROM_Trig();                      //触发EEPROM操作
  84.         DisableEEPROM();                    //禁止EEPROM操作
  85. }
  86. //========================================================================
  87. // 函数: void EEPROM_write_n(u32 EE_address,u8 *DataAddress,u16 number)
  88. // 描述: 把缓冲的n个字节写入指定首地址的EEPROM.
  89. // 参数: EE_address:  写入EEPROM的首地址.
  90. //       DataAddress: 写入源数据的缓冲的首地址.
  91. //       number:      写入的字节长度.
  92. // 返回: non.
  93. // 版本: V1.0, 2012-10-22
  94. //========================================================================
  95. void EEPROM_write_n(u32 EE_address,u8 *DataAddress,u16 number)
  96. {
  97.         IAP_ENABLE();                       //设置等待时间,允许IAP操作,送一次就够
  98.         IAP_WRITE();                        //宏调用, 送字节写命令
  99.         do
  100.         {
  101.                 IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
  102.                 IAP_ADDRH = (u8)(EE_address >> 8);  //送地址中字节(地址需要改变时才需重新送地址)
  103.                 IAP_ADDRL = (u8)EE_address;         //送地址低字节(地址需要改变时才需重新送地址)
  104.                 IAP_DATA  = *DataAddress;         //送数据到IAP_DATA,只有数据改变时才需重新送
  105.                 EEPROM_Trig();                    //触发EEPROM操作
  106.                 EE_address++;                     //下一个地址
  107.                 DataAddress++;                    //下一个数据
  108.         }while(--number);                   //直到结束
  109.         DisableEEPROM();
  110. }
复制代码
这个是官网下的库函数
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:21
  • 最近打卡:2025-06-03 09:09:20
已绑定手机

9

主题

61

回帖

313

积分

中级会员

积分
313
发表于 2025-3-6 10:51:49 | 显示全部楼层
  1. /*---------------------------------------------------------------------*/
  2. /* --- Web: www.STCAI.com ---------------------------------------------*/
  3. /*---------------------------------------------------------------------*/
  4. #include "AI8051U_EEPROM.h"
  5. //========================================================================
  6. // 函数: void ISP_Disable(void)
  7. // 描述: 禁止访问ISP/IAP.
  8. // 参数: non.
  9. // 返回: non.
  10. // 版本: V1.0, 2012-10-22
  11. //========================================================================
  12. void DisableEEPROM(void)
  13. {
  14.         IAP_CONTR = 0;                //禁止IAP操作
  15.         IAP_CMD   = 0;                //去除IAP命令
  16.         IAP_TRIG  = 0;                //防止IAP命令误触发
  17.         IAP_ADDRE = 0xff;   //将地址设置到非 IAP 区域
  18.         IAP_ADDRH = 0xff;   //将地址设置到非 IAP 区域
  19.         IAP_ADDRL = 0xff;
  20. }
  21. //========================================================================
  22. // 函数: void EEPROM_Trig(void)
  23. // 描述: 触发EEPROM操作.
  24. // 参数: none.
  25. // 返回: none.
  26. // 版本: V1.0, 2014-6-30
  27. //========================================================================
  28. void EEPROM_Trig(void)
  29. {
  30.         F0 = EA;    //保存全局中断
  31.         EA = 0;     //禁止中断, 避免触发命令无效
  32.         IAP_TRIG = 0x5A;
  33.         IAP_TRIG = 0xA5;                    //先送5AH,再送A5H到IAP触发寄存器,每次都需要如此
  34.                                                                                                                                                         //送完A5H后,IAP命令立即被触发启动
  35.                                                                                                                                                         //CPU等待IAP完成后,才会继续执行程序。
  36.         _nop_();   //由于AI8051U是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
  37.         _nop_();
  38.         _nop_();
  39.         _nop_();
  40.         EA = F0;    //恢复全局中断
  41. }
  42. //========================================================================
  43. // 函数: void EEPROM_read_n(u32 EE_address,u8 *DataAddress,u16 number)
  44. // 描述: 从指定EEPROM首地址读出n个字节放指定的缓冲.
  45. // 参数: EE_address:  读出EEPROM的首地址.
  46. //       DataAddress: 读出数据放缓冲的首地址.
  47. //       number:      读出的字节长度.
  48. // 返回: non.
  49. // 版本: V1.0, 2012-10-22
  50. //========================================================================
  51. void EEPROM_read_n(u32 EE_address,u8 *DataAddress,u16 number)
  52. {
  53.         IAP_ENABLE();                           //设置等待时间,允许IAP操作,送一次就够
  54.         IAP_READ();                             //送字节读命令,命令不需改变时,不需重新送命令
  55.         do
  56.         {
  57.                 IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
  58.                 IAP_ADDRH = (u8)(EE_address >> 8);  //送地址中字节(地址需要改变时才需重新送地址)
  59.                 IAP_ADDRL = (u8)EE_address;         //送地址低字节(地址需要改变时才需重新送地址)
  60.                 EEPROM_Trig();                      //触发EEPROM操作
  61.                 *DataAddress = IAP_DATA;            //读出的数据送往
  62.                 EE_address++;
  63.                 DataAddress++;
  64.         }while(--number);
  65.         DisableEEPROM();
  66. }
  67. //========================================================================
  68. // 函数: void EEPROM_SectorErase(u32 EE_address)
  69. // 描述: 把指定地址的EEPROM扇区擦除.
  70. // 参数: EE_address:  要擦除的扇区EEPROM的地址.
  71. // 返回: non.
  72. // 版本: V1.0, 2013-5-10
  73. //========================================================================
  74. void EEPROM_SectorErase(u32 EE_address)
  75. {
  76.         IAP_ENABLE();                       //设置等待时间,允许IAP操作,送一次就够
  77.         IAP_ERASE();                        //宏调用, 送扇区擦除命令,命令不需改变时,不需重新送命令
  78.                                                                                                                                                         //只有扇区擦除,没有字节擦除,512字节/扇区。
  79.                                                                                                                                                         //扇区中任意一个字节地址都是扇区地址。
  80.         IAP_ADDRE = (u8)(EE_address >> 16); //送扇区地址高字节(地址需要改变时才需重新送地址)
  81.         IAP_ADDRH = (u8)(EE_address >> 8);  //送扇区地址中字节(地址需要改变时才需重新送地址)
  82.         IAP_ADDRL = (u8)EE_address;         //送扇区地址低字节(地址需要改变时才需重新送地址)
  83.         EEPROM_Trig();                      //触发EEPROM操作
  84.         DisableEEPROM();                    //禁止EEPROM操作
  85. }
  86. //========================================================================
  87. // 函数: void EEPROM_write_n(u32 EE_address,u8 *DataAddress,u16 number)
  88. // 描述: 把缓冲的n个字节写入指定首地址的EEPROM.
  89. // 参数: EE_address:  写入EEPROM的首地址.
  90. //       DataAddress: 写入源数据的缓冲的首地址.
  91. //       number:      写入的字节长度.
  92. // 返回: non.
  93. // 版本: V1.0, 2012-10-22
  94. //========================================================================
  95. void EEPROM_write_n(u32 EE_address,u8 *DataAddress,u16 number)
  96. {
  97.         IAP_ENABLE();                       //设置等待时间,允许IAP操作,送一次就够
  98.         IAP_WRITE();                        //宏调用, 送字节写命令
  99.         do
  100.         {
  101.                 IAP_ADDRE = (u8)(EE_address >> 16); //送地址高字节(地址需要改变时才需重新送地址)
  102.                 IAP_ADDRH = (u8)(EE_address >> 8);  //送地址中字节(地址需要改变时才需重新送地址)
  103.                 IAP_ADDRL = (u8)EE_address;         //送地址低字节(地址需要改变时才需重新送地址)
  104.                 IAP_DATA  = *DataAddress;         //送数据到IAP_DATA,只有数据改变时才需重新送
  105.                 EEPROM_Trig();                    //触发EEPROM操作
  106.                 EE_address++;                     //下一个地址
  107.                 DataAddress++;                    //下一个数据
  108.         }while(--number);                   //直到结束
  109.         DisableEEPROM();
  110. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:21
  • 最近打卡:2025-06-03 09:09:20
已绑定手机

9

主题

61

回帖

313

积分

中级会员

积分
313
发表于 2025-3-6 10:52:10 | 显示全部楼层
_奶*** 发表于 2025-3-6 10:30
至少把读n 写n的代码也贴出来把,,,

还有就是32位模式下,,这样写的printf需要把u8的数组强转成16位么 ...

审核了,还没通过
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-6-17 15:22 , Processed in 0.195194 second(s), 97 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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