找回密码
 立即注册
查看: 40|回复: 9

写EEPROM遇到的问题

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:588
  • 最近打卡:2025-07-08 14:41:03

118

主题

2048

回帖

5955

积分

论坛元老

积分
5955
发表于 昨天 18:15 | 显示全部楼层 |阅读模式
芯片用stc8h2k12u,代码用AIapp-ISP-v6.95W中的范例修改
  1. #include "reg51.h"
  2. #include "intrins.h"
  3. #define FOSC        11059200UL
  4. #define BRT         (65536 - FOSC / 115200 / 4)
  5. sfr     P0M1    =   0x93;
  6. sfr     P0M0    =   0x94;
  7. sfr     P1M1    =   0x91;
  8. sfr     P1M0    =   0x92;
  9. sfr     P2M1    =   0x95;
  10. sfr     P2M0    =   0x96;
  11. sfr     P3M1    =   0xb1;
  12. sfr     P3M0    =   0xb2;
  13. sfr     P4M1    =   0xb3;
  14. sfr     P4M0    =   0xb4;
  15. sfr     P5M1    =   0xc9;
  16. sfr     P5M0    =   0xca;
  17. sfr     AUXR    =   0x8e;
  18. sfr     T2H     =   0xd6;
  19. sfr     T2L     =   0xd7;
  20. sfr     IAP_DATA    =   0xC2;
  21. sfr     IAP_ADDRH   =   0xC3;
  22. sfr     IAP_ADDRL   =   0xC4;
  23. sfr     IAP_CMD     =   0xC5;
  24. sfr     IAP_TRIG    =   0xC6;
  25. sfr     IAP_CONTR   =   0xC7;
  26. sfr     IAP_TPS     =   0xF5;
  27. void Delay1000ms(void)        //@11.0592MHz
  28. {
  29.         unsigned char data i, j, k;
  30.         i = 57;
  31.         j = 27;
  32.         k = 112;
  33.         do
  34.         {
  35.                 do
  36.                 {
  37.                         while (--k);
  38.                 } while (--j);
  39.         } while (--i);
  40. }
  41. void UartInit()
  42. {
  43.     SCON = 0x5a;
  44.     T2L = BRT;
  45.     T2H = BRT >> 8;
  46.     AUXR = 0x15;
  47. }
  48. void UartSend(char dat)
  49. {
  50.     while (!TI);
  51.     TI = 0;
  52.     SBUF = dat;
  53. }
  54. void IapIdle()
  55. {
  56.     IAP_CONTR = 0;                              //关闭IAP功能
  57.     IAP_CMD = 0;                                //清除命令寄存器
  58.     IAP_TRIG = 0;                               //清除触发寄存器
  59.     IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
  60.     IAP_ADDRL = 0;
  61. }
  62. char IapRead(int addr)
  63. {
  64.     char dat;
  65.     IAP_CONTR = 0x80;                           //使能IAP
  66.     IAP_TPS = 12;                               //设置等待参数12MHz
  67.     IAP_CMD = 1;                                //设置IAP读命令
  68.     IAP_ADDRL = addr;                           //设置IAP低地址
  69.     IAP_ADDRH = addr >> 8;                      //设置IAP高地址
  70.     IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
  71.     IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
  72.     _nop_();
  73.     dat = IAP_DATA;                             //读IAP数据
  74.     IapIdle();                                  //关闭IAP功能
  75.     return dat;
  76. }
  77. void IapProgram(int addr, char dat)
  78. {
  79.     IAP_CONTR = 0x80;                           //使能IAP
  80.     IAP_TPS = 12;                               //设置等待参数12MHz
  81.     IAP_CMD = 2;                                //设置IAP写命令
  82.     IAP_ADDRL = addr;                           //设置IAP低地址
  83.     IAP_ADDRH = addr >> 8;                      //设置IAP高地址
  84.     IAP_DATA = dat;                             //写IAP数据
  85.     IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
  86.     IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
  87.     _nop_();
  88.     IapIdle();                                  //关闭IAP功能
  89. }
  90. void IapErase(int addr)
  91. {
  92.     IAP_CONTR = 0x80;                           //使能IAP
  93.     IAP_TPS = 12;                               //设置等待参数12MHz
  94.     IAP_CMD = 3;                                //设置IAP擦除命令
  95.     IAP_ADDRL = addr;                           //设置IAP低地址
  96.     IAP_ADDRH = addr >> 8;                      //设置IAP高地址
  97.     IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
  98.     IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
  99.     _nop_();                                    //
  100.     IapIdle();                                  //关闭IAP功能
  101. }
  102. void Delay10ms(void)        //@11.0592MHz
  103. {
  104.         unsigned char data i, j;
  105.         _nop_();
  106.         _nop_();
  107.         i = 144;
  108.         j = 157;
  109.         do
  110.         {
  111.                 while (--j);
  112.         } while (--i);
  113. }
  114. void main()
  115. {
  116.         char i;
  117.     P0M0 = 0x00;
  118.     P0M1 = 0x00;
  119.     P1M0 = 0x00;
  120.     P1M1 = 0x00;
  121.     P2M0 = 0x00;
  122.     P2M1 = 0x00;
  123.     P3M0 = 0x00;
  124.     P3M1 = 0x00;
  125.     P4M0 = 0x00;
  126.     P4M1 = 0x00;
  127.     P5M0 = 0x00;
  128.     P5M1 = 0x00;
  129.     UartInit();
  130.         Delay1000ms();
  131.         Delay1000ms();
  132.     IapErase(0);
  133.         for(i=0;i<64;i++)
  134.                 UartSend(IapRead(i));
  135.         for(i=0;i<64;i++)
  136.         {
  137.                 IapProgram(i, i);
  138.         }
  139.         for(i=0;i<64;i++)
  140.         {        
  141.                 UartSend(IapRead(i));
  142.         }
  143.     while (1);
  144. }
复制代码
目前遇到的问题是,连续写入时,读出的数据好像被推后一个字节地址,不知道在哪个地方出问题。


工程如下:




008.jpg

001.rar

24.85 KB, 下载次数: 0

回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:230
  • 最近打卡:2025-07-08 08:46:53
已绑定手机

76

主题

2099

回帖

4708

积分

荣誉版主

无情的代码机器

积分
4708
发表于 昨天 18:26 | 显示全部楼层
楼主这个代码验证无法闭环呀~
  •     IapErase(0);//清空一个扇区
  •         for(i=0;i<64;i++)
  •                 UartSend(IapRead(i));  //这里必然全是空,0xFF
  •         for(i=0;i<64;i++)
  •         {
  •                 IapProgram(i, i);  //写入
  •         }
  •     UartSend(IapRead(i));// i64 ,并且64位置只擦除未写入,0xFF

三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:462
  • 最近打卡:2025-07-08 09:25:47
已绑定手机

40

主题

2103

回帖

7247

积分

论坛元老

积分
7247
发表于 昨天 18:27 | 显示全部楼层
用附件的例子烧录到芯片里试试,串口助手文本模式打印读写结果

STC8-EEPROM多字节读写操作-通过串口1输出.zip

8.28 KB, 下载次数: 1

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:588
  • 最近打卡:2025-07-08 14:41:03

118

主题

2048

回帖

5955

积分

论坛元老

积分
5955
发表于 昨天 18:30 | 显示全部楼层
乘风*** 发表于 2025-7-7 18:27
用附件的例子烧录到芯片里试试,串口助手文本模式打印读写结果

我试试看
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:588
  • 最近打卡:2025-07-08 14:41:03

118

主题

2048

回帖

5955

积分

论坛元老

积分
5955
发表于 昨天 22:05 | 显示全部楼层
乘风*** 发表于 2025-7-7 18:27
用附件的例子烧录到芯片里试试,串口助手文本模式打印读写结果

试了,你第二次读取是写入一个字节就读一个字节的,我把它改成先多个字节写入,再多个字节读取,就出问题了,依然出现字节移位的问题
代码如下:
  1. #include "reg51.h"
  2. #include "intrins.h"
  3. #include "stdio.h"
  4. #define FOSC        11059200UL
  5. #define BRT         (65536 - FOSC / 115200 / 4)
  6. sfr     P0M1    =   0x93;
  7. sfr     P0M0    =   0x94;
  8. sfr     P1M1    =   0x91;
  9. sfr     P1M0    =   0x92;
  10. sfr     P2M1    =   0x95;
  11. sfr     P2M0    =   0x96;
  12. sfr     P3M1    =   0xb1;
  13. sfr     P3M0    =   0xb2;
  14. sfr     P4M1    =   0xb3;
  15. sfr     P4M0    =   0xb4;
  16. sfr     P5M1    =   0xc9;
  17. sfr     P5M0    =   0xca;
  18. sfr     AUXR    =   0x8e;
  19. sfr     T2H     =   0xd6;
  20. sfr     T2L     =   0xd7;
  21. sfr     IAP_DATA    =   0xC2;
  22. sfr     IAP_ADDRH   =   0xC3;
  23. sfr     IAP_ADDRL   =   0xC4;
  24. sfr     IAP_CMD     =   0xC5;
  25. sfr     IAP_TRIG    =   0xC6;
  26. sfr     IAP_CONTR   =   0xC7;
  27. sfr     IAP_TPS     =   0xF5;
  28. void Delay1000ms(void)        //@11.0592MHz
  29. {
  30.         unsigned char data i, j, k;
  31.         i = 57;
  32.         j = 27;
  33.         k = 112;
  34.         do
  35.         {
  36.                 do
  37.                 {
  38.                         while (--k);
  39.                 } while (--j);
  40.         } while (--i);
  41. }
  42. void UartInit()
  43. {
  44.     SCON = 0x5a;
  45.     T2L = BRT;
  46.     T2H = BRT >> 8;
  47.     AUXR = 0x15;
  48. }
  49. void UartSend(char dat)
  50. {
  51.     while (!TI);
  52.     TI = 0;
  53.     SBUF = dat;
  54. }
  55. void IapIdle()
  56. {
  57.     IAP_CONTR = 0;                              //关闭IAP功能
  58.     IAP_CMD = 0;                                //清除命令寄存器
  59.     IAP_TRIG = 0;                               //清除触发寄存器
  60.     IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
  61.     IAP_ADDRL = 0;
  62. }
  63. unsigned char IapRead(int addr)
  64. {
  65.     char dat;
  66.     IAP_CONTR = 0x80;                           //使能IAP
  67.     IAP_CMD = 1;                                //设置IAP读命令
  68.     IAP_ADDRL = addr;                           //设置IAP低地址
  69.     IAP_ADDRH = addr >> 8;                      //设置IAP高地址
  70.     IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
  71.     IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
  72.     _nop_();
  73.     dat = IAP_DATA;                             //读IAP数据
  74.     IapIdle();                                  //关闭IAP功能
  75.     return dat;
  76. }
  77. void IapProgram(int addr, unsigned char dat)
  78. {
  79.     IAP_CONTR = 0x80;                           //使能IAP
  80.     IAP_CMD = 2;                                //设置IAP写命令
  81.     IAP_ADDRL = addr;                           //设置IAP低地址
  82.     IAP_ADDRH = addr >> 8;                      //设置IAP高地址
  83.     IAP_DATA = dat;                             //写IAP数据
  84.     IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
  85.     IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
  86.     _nop_();
  87.     IapIdle();                                  //关闭IAP功能
  88. }
  89. void IapErase(int addr)
  90. {
  91.     IAP_CONTR = 0x80;                           //使能IAP
  92.     IAP_CMD = 3;                                //设置IAP擦除命令
  93.     IAP_ADDRL = addr;                           //设置IAP低地址
  94.     IAP_ADDRH = addr >> 8;                      //设置IAP高地址
  95.     IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
  96.     IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
  97.     _nop_();                                    //
  98.     IapIdle();                                  //关闭IAP功能
  99. }
  100. void Delay10ms(void)        //@11.0592MHz
  101. {
  102.         unsigned char data i, j;
  103.         _nop_();
  104.         _nop_();
  105.         i = 144;
  106.         j = 157;
  107.         do
  108.         {
  109.                 while (--j);
  110.         } while (--i);
  111. }
  112. void main()
  113. {
  114.         char i;
  115. //        unsigned char a[64];
  116.     P0M0 = 0x00;
  117.     P0M1 = 0x00;
  118.     P1M0 = 0x00;
  119.     P1M1 = 0x00;
  120.     P2M0 = 0x00;
  121.     P2M1 = 0x00;
  122.     P3M0 = 0x00;
  123.     P3M1 = 0x00;
  124.     P4M0 = 0x00;
  125.     P4M1 = 0x00;
  126.     P5M0 = 0x00;
  127.     P5M1 = 0x00;
  128.     UartInit();
  129.     IAP_TPS = 11;                   //设置EEPROM操作等待参数(11.0592MHz),初始化设置一次即可       
  130.         Delay1000ms();
  131.         Delay1000ms();
  132.         printf("read1:\r\n");       
  133.         for(i=0;i<12;i++)
  134.                 printf("0x%02bx ",IapRead(i));       
  135.         printf("\r\nread2:\r\n");       
  136.     IapErase(0);       
  137.         for(i=0;i<12;i++)
  138.                 printf("0x%02bx ",IapRead(i));       
  139.         printf("\r\nread3:\r\n");       
  140.        
  141.         for(i=0;i<12;i++)
  142.         {
  143.                 IapProgram(i, i);
  144.                 printf("0x%02bx ",IapRead(i));
  145.         }
  146.        
  147.         Delay10ms();
  148.         printf("\r\nread4:\r\n");       
  149.         for(i=0;i<12;i++)
  150.         {
  151.                 printf("0x%02bx ",IapRead(i));
  152.         }
  153.     while (1);
  154. }
  155. void UartPutc(unsigned char dat)
  156. {
  157.         SBUF = dat;
  158.         while(TI == 0);
  159.         TI = 0;
  160. }
  161. char putchar(char c)
  162. {
  163.         UartPutc(c);
  164.         return c;
  165. }
复制代码



测试结果:

008.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:588
  • 最近打卡:2025-07-08 14:41:03

118

主题

2048

回帖

5955

积分

论坛元老

积分
5955
发表于 昨天 22:15 | 显示全部楼层
问题暂时解决:就是加长读取中的延时(增加一个或两个_nop_();)

原代码:
  1. unsigned char IapRead(int addr)
  2. {
  3.     char dat;
  4.     IAP_CONTR = 0x80;                           //使能IAP
  5.     IAP_CMD = 1;                                //设置IAP读命令
  6.     IAP_ADDRL = addr;                           //设置IAP低地址
  7.     IAP_ADDRH = addr >> 8;                      //设置IAP高地址
  8.     IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
  9.     IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
  10.         _nop_();
  11.     dat = IAP_DATA;                             //读IAP数据
  12.     IapIdle();                                  //关闭IAP功能
  13.     return dat;
  14. }
复制代码
改后代码:
  1. unsigned char IapRead(int addr)
  2. {
  3.     char dat;
  4.     IAP_CONTR = 0x80;                           //使能IAP
  5.     IAP_CMD = 1;                                //设置IAP读命令
  6.     IAP_ADDRL = addr;                           //设置IAP低地址
  7.     IAP_ADDRH = addr >> 8;                      //设置IAP高地址
  8.     IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
  9.     IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
  10.         _nop_();_nop_();//增加一个_nop_();
  11.     dat = IAP_DATA;                             //读IAP数据
  12.     IapIdle();                                  //关闭IAP功能
  13.     return dat;
  14. }
复制代码
估计是STC8执行代码的速度太快了的缘故吧!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:462
  • 最近打卡:2025-07-08 09:25:47
已绑定手机

40

主题

2103

回帖

7247

积分

论坛元老

积分
7247
发表于 10 小时前 | 显示全部楼层
例程为了简化代码,一个循环完成读写操作。
你想测试写完再读,再加一个循环就好了。
  1.     IAP_TPS = 11;       //设置EEPROM操作等待参数(11.0592MHz),初始化设置一次即可
  2.     PrintfInit();
  3.     printf("Read1=");   //读取EEPROM原先的内容
  4.     for(i=0;i<10;i++)
  5.     {
  6.         a[i] = IapRead(OFFSET+i);
  7.         printf("0x%02bx ",a[i]);
  8.         if(a[i] == 0xff) a[i] = i;  //如果内容为空,则写入初始化数据
  9.         else a[i]++;    //如果内容非空,在原先基础上加1
  10.     }
  11.     printf("\r\n");
  12.     IapErase(OFFSET);   //如果擦写范围跨扇区,需要擦除两个扇区的空间
  13.     for(i=0;i<10;i++)
  14.     {
  15.         IapProgram(OFFSET+i, a[i]);
  16.     }
  17.     printf("Read2=");   //擦除、重写后,读取EEPROM现在的内容
  18.     for(i=0;i<10;i++)
  19.     {
  20.         a[i] = IapRead(OFFSET+i);
  21.         printf("0x%02bx ",a[i]);
  22.     }
  23.     printf("\r\n");
复制代码

截图202507080925011821.jpg

STC8-EEPROM多字节读写操作-通过串口1输出.zip

16.99 KB, 下载次数: 2

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:588
  • 最近打卡:2025-07-08 14:41:03

118

主题

2048

回帖

5955

积分

论坛元老

积分
5955
发表于 5 小时前 | 显示全部楼层
乘风*** 发表于 2025-7-8 09:25
例程为了简化代码,一个循环完成读写操作。
你想测试写完再读,再加一个循环就好了。

读取时不加长延时(添加_nop_();)时,字节0出错:

2025-07-08_144513.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:462
  • 最近打卡:2025-07-08 09:25:47
已绑定手机

40

主题

2103

回帖

7247

积分

论坛元老

积分
7247
发表于 4 小时前 | 显示全部楼层
xxkj*** 发表于 2025-7-8 14:49
读取时不加长延时(添加_nop_();)时,字节0出错:

先不要修改例子,直接用例子测试,功能验证正常后再进行修改或者移植。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:588
  • 最近打卡:2025-07-08 14:41:03

118

主题

2048

回帖

5955

积分

论坛元老

积分
5955
发表于 2 小时前 | 显示全部楼层
乘风*** 发表于 2025-7-8 15:20
先不要修改例子,直接用例子测试,功能验证正常后再进行修改或者移植。 ...

我是直接下载你发的那个工程的,没有修改,结果出现小问题。我用的芯片是STC8H2K12U-SOP16,如果用STC8H8K64U,就没有问题。
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-7-8 19:52 , Processed in 0.134631 second(s), 105 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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