找回密码
 立即注册
查看: 76|回复: 11

请教前辈STC15F2K32S2-LQFP44的EEPROM操作能不能这样

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:356
  • 最近打卡:2026-05-01 08:21:17
已绑定手机

56

主题

230

回帖

2058

积分

金牌会员

积分
2058
发表于 2026-4-20 13:28:45 | 显示全部楼层 |阅读模式
就像8C32那样使用低压中断快速保存一些失电后需要保存的数据

看到工具里面的选项又一个低压禁止EEPROM操作
不勾选的话能不能行?EEPROM在多低电压下还能继续操作?
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:60
  • 最近打卡:2026-05-01 05:53:11
已绑定手机

3

主题

94

回帖

505

积分

高级会员

积分
505
发表于 2026-4-20 13:42:16 | 显示全部楼层
  1. //测试条件:TX-1C实验板,转换板MCU型号IAP15W4K58S4,系统时钟11.0592MHz
  2. //注意:测试本示例时,需在ISP下载时将低压复位功能和低压时禁止EEPROM操作关闭
  3. #include "STC15Fxxxx.H"
  4. #include <intrins.h>                                //库头文件
  5. #define uint unsigned int                         //宏定义数据类型uint
  6. #define uchar unsigned char                 //宏定义数据类型uchar
  7. //宏定义ISP的操作命令
  8. #define CMD_IDLE    0               //空闲模式
  9. #define CMD_READ    1               //IAP字节读命令
  10. #define CMD_PROGRAM 2               //IAP字节编程命令
  11. #define CMD_ERASE   3               //IAP扇区擦除命令
  12. #define ENABLE_IAP  0x82            //CPU的等待时间
  13. #define IAP_ADDRESS 0x0800                        //测试地址
  14. sbit duan=P2^6;
  15. sbit wein=P2^7;
  16. //顺序共阴极数码管段码表,段码a-h顺序接PX0-PX7
  17. uchar code table[]={//共阴数码管段码"0~f-."
  18.                 0x3f,0x06,0x5b,0x4f,
  19.                 0x66,0x6d,0x7d,0x07,
  20.                 0x7f,0x6f,0x77,0x7c,
  21.                 0x39,0x5e,0x79,0x71,0x40,0x80};
  22. uchar data dis_buf[8];                //缓存数组
  23. uint num,sec;
  24. uchar i;
  25. void Timer0Init();                                        //定时器初始化声明
  26. void IapIdle();                                                //关闭IAP/EEPROM
  27. uchar IapReadByte(uint addr);                //读取EEPROM数据
  28. void IapProgramByte(uint addr, uchar dat);//写入EEPROM数据
  29. void IapEraseSector(uint addr);                //擦除EEPROM数据
  30. void main()                                                       
  31. {
  32.         P0M0 = 0x00;
  33.         P0M1 = 0x00;
  34.         P1M0 = 0x00;
  35.         P1M1 = 0x00;
  36.         P2M0 = 0x00;
  37.         P2M1 = 0x00;
  38.         P3M0 = 0x00;
  39.         P3M1 = 0x00;
  40.         P4M0 = 0x00;
  41.         P4M1 = 0x00;
  42.         P5M0 = 0x00;
  43.         P5M1 = 0x00;
  44.         P6M0 = 0x00;
  45.         P6M1 = 0x00;
  46.         P7M0 = 0x00;
  47.         P7M1 = 0x00;
  48.         sec=IapReadByte(IAP_ADDRESS)<<8|IapReadByte(IAP_ADDRESS+1);//读取保存的数据 用时11.75us
  49.         if(sec==0xffff)//如果没有保存数据
  50.                 sec=0;//变量为0
  51.         else IapEraseSector(IAP_ADDRESS);//擦除数据,为下次掉电保存数据做准备
  52.         PCON &= 0xDF;//清0掉电标志
  53.         ELVD = 1;//开低压中断
  54.         EA   = 1;//开总中断
  55.         Timer0Init();//初始化定时器
  56.         while(1)
  57.         {
  58.                 if(TF0)//查询T0中断请求标志
  59.                 {               
  60.                         TF0=0;//T0中断请求标志清0
  61.                         if(++num>=1000)//1秒
  62.                         {
  63.                                 num=0;                               
  64.                                 sec++;
  65.                         }
  66.                         dis_buf[0]=table[sec/10000%10];
  67.                         dis_buf[1]=table[sec/1000%10];
  68.                         dis_buf[2]=table[sec/100%10];
  69.                         dis_buf[3]=table[sec/10%10];
  70.                         dis_buf[4]=table[sec%10];
  71.                         P0=0x00;duan=1;duan=0;
  72.                         P0=~(0x01<<i);wein=1;wein=0;
  73.                         P0=dis_buf[i];duan=1;duan=0;
  74.                         i=++i%5;
  75.                 }
  76.         }
  77. }
  78. void Timer0Init(void)        //1毫秒@11.0592MHz
  79. {
  80.         AUXR |= 0x80;                //定时器时钟1T模式
  81.         TMOD &= 0xF0;                //设置定时器模式
  82.         TL0 = 0xCD;                        //设置定时初始值
  83.         TH0 = 0xD4;                        //设置定时初始值
  84.         TF0 = 0;                        //清除TF0标志
  85.         TR0 = 1;                        //定时器0开始计时
  86. }
  87. /*----------------------------
  88.         关闭IAP功能
  89. ----------------------------*/
  90. void IapIdle()
  91. {
  92.     IAP_CONTR = 0;                  //关闭IAP功能
  93.     IAP_CMD = 0;                    //清除命令寄存器
  94.     IAP_TRIG = 0;                   //清除触发寄存器
  95.     IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
  96.     IAP_ADDRL = 0;
  97. }
  98. /*----------------------------
  99. 从ISP/IAP/EEPROM区域读取一字节
  100. ----------------------------*/
  101. uchar IapReadByte(uint addr)
  102. {
  103.     uchar dat;                       //数据缓冲区
  104.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  105.     IAP_CMD = CMD_READ;             //设置IAP命令
  106.     IAP_ADDRL = addr;               //设置IAP低地址
  107.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  108.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  109.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  110.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  111.     dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
  112.     IapIdle();                      //关闭IAP功能
  113.     return dat;                     //返回
  114. }
  115. /*-------------------------------
  116. 写一字节数据到ISP/IAP/EEPROM区域
  117. --------------------------------*/
  118. void IapProgramByte(uint addr, uchar dat)
  119. {
  120.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  121.     IAP_CMD = CMD_PROGRAM;          //设置IAP命令
  122.     IAP_ADDRL = addr;               //设置IAP低地址
  123.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  124.     IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
  125.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  126.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  127.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  128.     IapIdle();                      //关闭IAP功能
  129. }
  130. /*----------------------------
  131. ISP/IAP/EEPROM扇区擦除
  132. ----------------------------*/
  133. void IapEraseSector(uint addr)
  134. {
  135.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  136.     IAP_CMD = CMD_ERASE;            //设置IAP命令
  137.     IAP_ADDRL = addr;               //设置IAP低地址
  138.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  139.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  140.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  141.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  142.     IapIdle();                      //关闭IAP功能
  143. }
  144. void PowerLost() interrupt 6                //剩余电量从中断开始到完全断电2.5ms
  145. {
  146.         EA = 0;                                                //关闭总中断
  147.         P0M1 = 0xff;                                //所有端口高阻用时2.75us
  148.         P1M1 = 0xff;
  149.         P2M1 = 0xff;
  150.         P3M1 = 0xff;
  151.         P4M1 = 0xff;
  152.         P5M1 = 0xff;
  153.         P6M1 = 0xff;
  154.         P7M1 = 0xff;
  155.         IapProgramByte(IAP_ADDRESS,sec>>8);//写数据高8位到EEPROM
  156.         IapProgramByte(IAP_ADDRESS+1,sec);//写数据低8位到EEPROM  写两个字节用时215.25us
  157.         while((PCON & 0x20) != 0)         //复查低压标志
  158.         {
  159.                 PCON &= 0xDF;                  //清除低压标志
  160.                 _nop_();               
  161.                 _nop_();                            //坐等掉电
  162.         }
  163.         IAP_CONTR = 0x20;                 //发现是误报,重启单片机,恢复正常工作
  164. }
复制代码
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:356
  • 最近打卡:2026-05-01 08:21:17
已绑定手机

56

主题

230

回帖

2058

积分

金牌会员

积分
2058
发表于 2026-4-20 13:45:58 | 显示全部楼层

你这是15W的,我现在是15F,只能在5V工作,8C的也是宽电压的,我试过,可以用,测试很多次也挺可靠的
但是15W不知道啥情况
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:60
  • 最近打卡:2026-05-01 05:53:11
已绑定手机

3

主题

94

回帖

505

积分

高级会员

积分
505
发表于 2026-4-20 13:50:07 | 显示全部楼层
xiaob*** 发表于 2026-4-20 13:45
你这是15W的,我现在是15F,只能在5V工作,8C的也是宽电压的,我试过,可以用,测试很多次也挺可靠的
但 ...

此程序在STC8H3K48S2实验板上也能用,上面示例使用的芯片型号IAP15F2K61S2。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:356
  • 最近打卡:2026-05-01 08:21:17
已绑定手机

56

主题

230

回帖

2058

积分

金牌会员

积分
2058
发表于 2026-4-20 14:10:46 | 显示全部楼层
wul*** 发表于 2026-4-20 13:50
此程序在STC8H3K48S2实验板上也能用,上面示例使用的芯片型号IAP15F2K61S2。

哦,拿我试试
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:356
  • 最近打卡:2026-05-01 08:21:17
已绑定手机

56

主题

230

回帖

2058

积分

金牌会员

积分
2058
发表于 2026-4-20 16:17:50 | 显示全部楼层
试过了,低压中断选4.64V,取消勾选低压禁止EEPROM操作,就可以实现,测试代码是两个INT,4个字节,测试了几次,就用工具里面哪个电源开关。还好。
那么问题来了,可以选的最低电压是多少?
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:60
  • 最近打卡:2026-05-01 05:53:11
已绑定手机

3

主题

94

回帖

505

积分

高级会员

积分
505
发表于 2026-4-20 16:58:55 | 显示全部楼层
xiaob*** 发表于 2026-4-20 16:17
试过了,低压中断选4.64V,取消勾选低压禁止EEPROM操作,就可以实现,测试代码是两个INT,4个字节,测试了 ...

低压选多少V需要综合考虑。此例板上电源滤波电容10uf,选4.64V足可以维持写4个字节。此例中的一个重要技巧是加电时读取EEPROM数据后即擦除,为下次掉电保存数据做准备。因为擦除EEPROM耗时较长,不利于掉电后的操作时长。如果需要保存的数据较多就要适当增加电源滤波电容容量。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:356
  • 最近打卡:2026-05-01 08:21:17
已绑定手机

56

主题

230

回帖

2058

积分

金牌会员

积分
2058
发表于 2026-4-20 17:19:10 | 显示全部楼层
wul*** 发表于 2026-4-20 16:58
低压选多少V需要综合考虑。此例板上电源滤波电容10uf,选4.64V足可以维持写4个字节。此例中的一个重要技 ...

我是怕选的太低就不能操作EEPROM了
现在的电容是470uF的,前边有34063,变压器是12V的,12V滤波是1000uF
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:234
  • 最近打卡:2026-04-30 01:26:24
已绑定手机

22

主题

401

回帖

1816

积分

金牌会员

DIY玩家

积分
1816
发表于 2026-4-20 17:56:36 | 显示全部楼层
xiaob*** 发表于 2026-4-20 17:19
我是怕选的太低就不能操作EEPROM了
现在的电容是470uF的,前边有34063,变压器是12V的,12V滤波是1000uF ...

供电突然电压急剧降低
储能电容可以供电的时间如何推算
真正的学徒往往怀着大师的心
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:356
  • 最近打卡:2026-05-01 08:21:17
已绑定手机

56

主题

230

回帖

2058

积分

金牌会员

积分
2058
发表于 2026-4-20 18:08:15 | 显示全部楼层
狂热*** 发表于 2026-4-20 17:56
供电突然电压急剧降低
储能电容可以供电的时间如何推算

不懂啊,都不知道降低到多少会导致写EEPROM失败,咋算?系统消耗电流也不知道啊,显示可能要几百毫安,关键是实际使用时有可能多个输出继电器是吸合的,如此12V那端也会消耗很快。所以我之前的设计需要掉电保存时通常都是使用12V那端的降低做的,这样5V这端会有重组的时间做出响应,都不需要预先擦除。甚至不需要中断,直接用扫描,在消抖几十个MS之后从容的先擦除再写入,都很可靠
现在这个是早就做好的板子,当时也没有要求掉电保存。所有没有相关的硬件支持,只能在低压中断上想办法。也不知道是不是可靠。
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-5-1 10:30 , Processed in 0.134154 second(s), 95 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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