找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 147|回复: 4
打印 上一主题 下一主题
收起左侧

求一个STC15断电记忆的EEPROM代码

[复制链接]
跳转到指定楼层
楼主
ID:33548 发表于 2025-6-2 21:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:390416 发表于 2025-6-2 23:31 | 只看该作者
#include "all.h"                                                                 //从工程目录下》c_and_h文件夹查找all文件
volatile u8 code EEPROM_Flash[512] _at_ 0x4000;        //指定EEPROM的存储空间地址                       

//************************************************************************************  
// EEPROM IAP 擦除整个扇区
//************************************************************************************  
void EEPROM_Wipe512_Drive(u8 AddrH)
{
        IAP_ADDRH=AddrH;
        IAP_CMD=0x03;
        IAP_CONTR|=0x82;
        //IAP_TPS=30;                                                                        //为了兼容STC8H系列而出现,STC15W视频教程没有这行,STC8A8K也没有这一行
        IAP_TRIG=0x5a;
        IAP_TRIG=0xa5;
}

//************************************************************************************  
// EEPROM IAP 向某个地址 保存数据
//************************************************************************************  
void EEPROM_Write_Byte_Drive(u8 AddrH,u8 AddrL,u8 Dat)
{
        IAP_ADDRH=AddrH;
        IAP_ADDRL=AddrL;
        IAP_DATA=Dat;
        IAP_CMD=0x02;
        IAP_CONTR|=0x82;
        //IAP_TPS=30;                                                                        //为了兼容STC8H系列而出现,STC15W视频教程没有这行,STC8A8K也没有这一行
        IAP_TRIG=0x5a;
        IAP_TRIG=0xa5;
}

//************************************************************************************  
// EEPROM IAP 从某个地址复制数据
//************************************************************************************  
u8 EEPROM_Read_Byte_Drive(u8 AddrH,u8 AddrL)
{
        u8 Dat;
        IAP_ADDRH=AddrH;
        IAP_ADDRL=AddrL;
        IAP_CMD=0x01;
        IAP_CONTR|=0x82;
        //IAP_TPS=30;                                                                        //为了兼容STC8H系列而出现,STC15W视频教程没有这行,STC8A8K也没有这一行
        IAP_TRIG=0x5a;
        IAP_TRIG=0xa5;
        Dat=IAP_DATA;
        return Dat;
}

回复

使用道具 举报

板凳
ID:390416 发表于 2025-6-2 23:31 | 只看该作者
kkk=EEPROM_Read_Byte_Drive(0,0);                                                        //EEPROM读出上次记忆的数据
        kkk++;
        EEPROM_Wipe512_Drive(0);                                                                        //擦除整个扇区
        EEPROM_Write_Byte_Drive(0,0,kkk);
回复

使用道具 举报

地板
ID:1133081 发表于 2025-6-3 07:06 | 只看该作者
可以参考这个测试程序
  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. }


复制代码
回复

使用道具 举报

5#
ID:1109793 发表于 2025-6-3 07:34 | 只看该作者
断电记忆关键在及时取得断电信号以及在断电后持续的供电直到保存的代码完成。
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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