找回密码
 立即注册
查看: 33|回复: 6

stc8g1k08a-8pin的eeprom区擦写问题

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2026-06-02 14:03:20

1

主题

3

回帖

11

积分

新手上路

积分
11
发表于 昨天 14:03 | 显示全部楼层 |阅读模式
我在用stc8g1k08a-8pin这款芯片做一个电路的定时控制装置,预计定时一年来控制这条线路的通断,程序上电后开始计时,期间可以断电,断电前将已经计时的数据保存到EEPROM中,这样下次上电,程序可以继续上次断电前保存的计时数据接着计时,直到总计时累积到总设定:一年,我的程序是按秒计时,每秒写入一次EEPROM,一年也就是三百多万次,我的问题是,这款芯片是否支持这么多次的EEPROM的擦写次数?还有就是如果不能,有没有在既保证芯片的使用寿命的前提下,又能够用其他方法解决?又或者是更改程序逻辑,亦或是说更换硬件芯片?
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:123
  • 最近打卡:2026-06-02 09:22:08
已绑定手机

4

主题

303

回帖

6278

积分

论坛元老

积分
6278
发表于 昨天 15:06 | 显示全部楼层
建议在掉电时写一次就好,可利用LVD低压检测中断或自带比较器进行掉电检测。
哪怕是十秒或一分钟写一次也比每秒写一次长寿。

或者每次换个地方写入,参考《重磅开源:具有均衡磨损算法的FLASH模拟EEPROM函数,彻底抛弃24c02/04/08 》:
https://www.stcaimcu.com/forum.p ... =6019&extra=&page=1

一天的秒数应是:24*60*60=86400,也就是八万多秒,一年应有三千多万秒,不知你的“三百多万次”怎么来的,考虑一下。



回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2026-06-02 14:03:20

1

主题

3

回帖

11

积分

新手上路

积分
11
发表于 昨天 15:28 | 显示全部楼层
lcws*** 发表于 2026-6-2 15:06
建议在掉电时写一次就好,可利用LVD低压检测中断或自带比较器进行掉电检测。
哪怕是十秒或一分钟写一次也比 ...

好的,我研究研究,感谢。
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2026-06-02 14:03:20

1

主题

3

回帖

11

积分

新手上路

积分
11
发表于 昨天 15:29 | 显示全部楼层
lcws*** 发表于 2026-6-2 15:06
建议在掉电时写一次就好,可利用LVD低压检测中断或自带比较器进行掉电检测。
哪怕是十秒或一分钟写一次也比 ...

好的,感谢
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2026-06-02 14:03:20

1

主题

3

回帖

11

积分

新手上路

积分
11
发表于 昨天 15:29 | 显示全部楼层
lcws*** 发表于 2026-6-2 15:06
建议在掉电时写一次就好,可利用LVD低压检测中断或自带比较器进行掉电检测。
哪怕是十秒或一分钟写一次也比 ...

感谢,我研究研究
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:361
  • 最近打卡:2026-06-02 10:56:34

85

主题

7431

回帖

1万

积分

超级版主

积分
16100
发表于 昨天 17:21 | 显示全部楼层
EEPROM本身不能支持百万次级别的擦写次数,有两个方法可以实现:
1、“滚动擦写”,比如使用4个扇区2048字节,写一次是4个字节,则要写512次才是一个擦写周期,官方擦写次数是10万次,这样就可以等效擦写5120万次。
2、断电保存,检测到断电,就擦除写入。
回复

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:91
  • 最近打卡:2026-06-02 07:14:09
已绑定手机

3

主题

154

回帖

737

积分

高级会员

积分
737
发表于 昨天 17:22 | 显示全部楼层
这个测试程序适用于STC8系列

  1. //测试条件:STC8H实验板,MCU型号STC8H3K48S2
  2. //注意:测试本示例时,需在ISP下载时将【允许低压复位(禁止低压中断)】关闭
  3. #include <STC8H.H>
  4. #include <intrins.h>                                //库头文件
  5. #define uint unsigned int                         //宏定义数据类型uint
  6. #define uchar unsigned char                 //宏定义数据类型uchar
  7. #define IAP_ADDRESS 0x0000                        //测试地址
  8. //顺序共阴极数码管段码表,段码a-h顺序接PX0-PX7
  9. uchar code table[]={//共阴数码管段码"0~f-."
  10.                 0x3f,0x06,0x5b,0x4f,
  11.                 0x66,0x6d,0x7d,0x07,
  12.                 0x7f,0x6f,0x77,0x7c,
  13.                 0x39,0x5e,0x79,0x71,0x40,0x80};
  14. uchar data dis_buf[8];              //缓存数组
  15. uint  num,sec;
  16. uchar i;
  17. uint  sign;
  18. void  Timer0Init();                 //定时器初始化声明
  19. void  IapIdle();                    //关闭IAP/EEPROM
  20. uchar IapRead(uint addr);           //读取EEPROM数据
  21. void  IapProgram(uint addr, uchar dat);//写入EEPROM数据
  22. void  IapErase(uint addr);          //擦除EEPROM扇区
  23. //初始化单片机端口
  24. void McuInit()
  25. {
  26.         P0M0 = 0xff; P0M1 = 0x00;
  27.         P1M0 = 0x00; P1M1 = 0x00;
  28.         P2M0 = 0x00; P2M1 = 0x00;
  29.         P3M0 = 0x00; P3M1 = 0x00;
  30.         P4M0 = 0x00; P4M1 = 0x00;
  31.         P5M0 = 0x00; P5M1 = 0x00;
  32.         P6M0 = 0x00; P6M1 = 0x00;
  33.         P7M0 = 0x00; P7M1 = 0x00;
  34. }
  35. //关闭单片机端口
  36. void McuSleep()
  37. {
  38.         P0M0 = 0x00; P0M1 = 0xff;
  39.         P1M0 = 0x00; P1M1 = 0xff;
  40.         P2M0 = 0x00; P2M1 = 0xff;
  41.         P3M0 = 0x00; P3M1 = 0xff;
  42.         P4M0 = 0x00; P4M1 = 0xff;
  43.         P5M0 = 0x00; P5M1 = 0xff;
  44.         P6M0 = 0x00; P6M1 = 0xff;
  45.         P7M0 = 0x00; P7M1 = 0xff;
  46. }
  47. void main()                                                       
  48. {
  49.         McuInit();
  50.         if(IapRead(IAP_ADDRESS)==0xff)//如果没有保存过数据
  51.         {
  52.                 IapProgram(IAP_ADDRESS, 0);//扇区首地址写0
  53.                 sec=0;
  54.                 sign=1;
  55.         }
  56.         else
  57.         {
  58. //                for(i=1;i<12;i++)         //测试写10次
  59.                 for(i=1;i<511;i++)        //测试写满510个字节
  60.                 {
  61.                         if(IapRead(IAP_ADDRESS+i)==0xff)//如果遇到没有保存数据的单元
  62.                         {
  63.                                 sec=IapRead(IAP_ADDRESS+i-1);//读取前一个字节保存的数据
  64.                                 sign=i;           //地址缓存
  65.                                 break;            //跳出循环
  66.                         }
  67.                 }
  68.         }
  69. //        if(sign==11)                  //测试写10次
  70.         if(sign==510)                 //如果写满510
  71.         {
  72.                 IapErase(IAP_ADDRESS);    //擦除扇区
  73.                 IapProgram(IAP_ADDRESS, 0);//首地址写0
  74.                 sign=1;
  75.         }
  76.         PCON &= 0xDF;                 //清0掉电标志
  77.         ELVD = 1;                     //开低压中断
  78.         EA   = 1;                     //开总中断
  79.         Timer0Init();                 //初始化定时器
  80.         while(1)
  81.         {
  82.                 if(TF0)                   //查询T0中断请求标志
  83.                 {               
  84.                         TF0=0;                //T0中断请求标志清0
  85.                         if(++num>=1000)       //1秒
  86.                         {
  87.                                 num=0;                               
  88.                                 sec=++sec%250;
  89.                         }
  90.                         dis_buf[0]=table[sec/100%10];
  91.                         dis_buf[1]=table[sec/10%10];
  92.                         dis_buf[2]=table[sec%10];
  93.                         P0=0x00;              //段消隐
  94.                         P2=~(0x01<<i);        //送位码
  95.                         P0=dis_buf[i];        //送段码
  96.                         i=++i%3;              //循环计数
  97.                 }//耗时569us
  98.         }
  99. }
  100. void PowerLost() interrupt 6      //低压中断
  101. {
  102.         EA = 0;                       //关闭总中断
  103.         McuSleep();                   //关闭所有端口(停止所有耗电电路)
  104.         IapProgram(IAP_ADDRESS+sign,sec);//写数据到EEPROM
  105.         while((PCON & 0x20) != 0)     //复查低压标志
  106.         {
  107.                 PCON &= 0xDF;             //清除低压标志
  108.                 _nop_();               
  109.                 _nop_();                  //坐等掉电
  110.         }
  111.         IAP_CONTR = 0x20;             //发现是误报,重启单片机,恢复正常工作
  112. }
  113. void Timer0Init(void)             //1毫秒@11.0592MHz
  114. {
  115.         AUXR |= 0x80;                 //定时器时钟1T模式
  116.         TMOD &= 0xF0;                 //设置定时器模式
  117.         TL0 = 0xCD;                   //设置定时初始值
  118.         TH0 = 0xD4;                   //设置定时初始值
  119.         TF0 = 0;                      //清除TF0标志
  120.         TR0 = 1;                      //定时器0开始计时
  121. }
  122. //关闭IAP/EEPROM
  123. void IapIdle()
  124. {
  125.     IAP_CONTR = 0;                //关闭IAP功能
  126.     IAP_CMD = 0;                  //清除命令寄存器
  127.     IAP_TRIG = 0;                 //清除触发寄存器
  128.     IAP_ADDRH = 0x80;             //将地址设置到非IAP区域
  129.     IAP_ADDRL = 0;
  130. }
  131. //读取EEPROM数据
  132. uchar IapRead(uint addr)
  133. {
  134.     uchar dat;
  135.     IAP_CONTR = 0x80;             //使能IAP
  136.     IAP_TPS = 12;                 //设置等待参数12MHz
  137.     IAP_CMD = 1;                  //设置IAP读命令
  138.     IAP_ADDRL = addr;             //设置IAP低地址
  139.     IAP_ADDRH = addr >> 8;        //设置IAP高地址
  140.     IAP_TRIG = 0x5a;              //写触发命令(0x5a)
  141.     IAP_TRIG = 0xa5;              //写触发命令(0xa5)
  142.     _nop_();
  143.     dat = IAP_DATA;               //读IAP数据
  144.     IapIdle();                    //关闭IAP功能
  145.     return dat;
  146. }
  147. //写入EEPROM数据
  148. void IapProgram(uint addr, uchar dat)
  149. {
  150.     IAP_CONTR = 0x80;             //使能IAP
  151.     IAP_TPS = 12;                 //设置等待参数12MHz
  152.     IAP_CMD = 2;                  //设置IAP写命令
  153.     IAP_ADDRL = addr;             //设置IAP低地址
  154.     IAP_ADDRH = addr >> 8;        //设置IAP高地址
  155.     IAP_DATA = dat;               //写IAP数据
  156.     IAP_TRIG = 0x5a;              //写触发命令(0x5a)
  157.     IAP_TRIG = 0xa5;              //写触发命令(0xa5)
  158.     _nop_();
  159.     IapIdle();                    //关闭IAP功能
  160. }
  161. void IapErase(uint addr)
  162. {
  163.     IAP_CONTR = 0x80;             //使能IAP
  164.     IAP_TPS = 12;                 //设置等待参数12MHz
  165.     IAP_CMD = 3;                  //设置IAP擦除命令
  166.     IAP_ADDRL = addr;             //设置IAP低地址
  167.     IAP_ADDRH = addr >> 8;        //设置IAP高地址
  168.     IAP_TRIG = 0x5a;              //写触发命令(0x5a)
  169.     IAP_TRIG = 0xa5;              //写触发命令(0xa5)
  170.     _nop_();                      //
  171.     IapIdle();                    //关闭IAP功能
  172. }
复制代码


回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-6-3 02:10 , Processed in 0.119081 second(s), 78 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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