找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2384|回复: 9
收起左侧

52单片机掉电存储功能怎么通过代码实现

[复制链接]
ID:398949 发表于 2021-5-23 19:23 | 显示全部楼层 |阅读模式
求STC89C52单片机关掉电源之后能把程序中的某个变量(比如说a)保存下来,下次启动之后还是变成上次的数据。比如第一次用的时候a=100而关电源时是a=200,;那么下次开机时a=200....一次类推,不希望用到硬件功能
回复

使用道具 举报

ID:752974 发表于 2021-5-24 08:32 | 显示全部楼层
  52内部没有EEPROM,要实现这个功能需要外挂个存储器,如24系列。
回复

使用道具 举报

ID:189235 发表于 2021-5-24 08:39 | 显示全部楼层

老铁,STC89C52内部有4KEEPROM,下载软件里面有例程
回复

使用道具 举报

ID:170318 发表于 2021-5-24 09:08 | 显示全部楼层
将a存储到EEprom里,下次启动后读取这个值,并将这个值给a,接着这a的值继续。如果有其它功能时,对读取EEprom的值进行判断,再执行下一步的工作
回复

使用道具 举报

ID:213173 发表于 2021-5-24 09:40 | 显示全部楼层
STC89C52单片机掉电之后,保存在EEPROM的数据不会丢失。但这里有一个问题,写EEPROM是有一定寿命的,大约30万次。为了在设备使用年限内不至于EEPROM失效,不宜太频繁改写EEPROM,只在掉电时把特定数据写入EEPROM保存。如果完全不依赖硬件功能想达到掉电保存EEPROM不太可靠。因为写EEPROM需要电源和时间。从单片机检测到掉电到数据保存到EEPROM必须要使电源维持最低限度。通常是用较大的电解电容维持电源电压数十ms。对此增加的成本可以忽略。
回复

使用道具 举报

ID:926217 发表于 2021-5-24 09:43 | 显示全部楼层
保存数据到flash
回复

使用道具 举报

ID:554500 发表于 2021-5-24 09:59 | 显示全部楼层
STC89C52内部没有EEPROM,没办法掉电保存。总不能加个备用电源吧。
可以选STC其他系列的单片机,内部带EEPROM的。这样不就能解决了!
回复

使用道具 举报

ID:398949 发表于 2021-5-24 13:50 | 显示全部楼层
wulin 发表于 2021-5-24 09:40
STC89C52单片机掉电之后,保存在EEPROM的数据不会丢失。但这里有一个问题,写EEPROM是有一定寿命的,大约30 ...

大佬,可以问一下这个电解电容维持电源可以不用嘛,只用低电压检测中断是否可以保证数据写入
回复

使用道具 举报

ID:213173 发表于 2021-5-24 14:33 | 显示全部楼层
universe 发表于 2021-5-24 13:50
大佬,可以问一下这个电解电容维持电源可以不用嘛,只用低电压检测中断是否可以保证数据写入

如果你有其它方法在掉电后还能维持VCC持续到写完EEPROM当然可以不用电解电容。但目前还没有哪个方案比这成本更低。
回复

使用道具 举报

ID:883031 发表于 2021-5-24 15:10 | 显示全部楼层
#include "reg51.h"
#include "intrins.h"

typedef unsigned char BYTE;
typedef unsigned int WORD;

/*Declare SFR associated with the IAP */
sfr IAP_DATA    =   0xE2;           //Flash data register
sfr IAP_ADDRH   =   0xE3;           //Flash address HIGH
sfr IAP_ADDRL   =   0xE4;           //Flash address LOW
sfr IAP_CMD     =   0xE5;           //Flash command register
sfr IAP_TRIG    =   0xE6;           //Flash command trigger
sfr IAP_CONTR   =   0xE7;           //Flash control register

/*Define ISP/IAP/EEPROM command*/
#define CMD_IDLE    0               //Stand-By
#define CMD_READ    1               //Byte-Read
#define CMD_PROGRAM 2               //Byte-Program
#define CMD_ERASE   3               //Sector-Erase

/*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
//#define ENABLE_IAP 0x80           //if SYSCLK<40MHz
#define ENABLE_IAP   0x81           //if SYSCLK<20MHz
//#define ENABLE_IAP x82            //if SYSCLK<10MHz
//#define ENABLE_IAP 0x83           //if SYSCLK<5MHz

//Start address for STC89C58xx EEPROM
#define IAP_ADDRESS 0x08000

void Delay(BYTE n);
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);

void main()
{
    WORD i;

    P1 = 0xfe;                      //1111,1110 System Reset OK
    Delay(10);                      //Delay
    IapEraseSector(IAP_ADDRESS);    //Erase current sector
    for (i=0; i<512; i++)           //Check whether all sector data is FF
    {
        if (IapReadByte(IAP_ADDRESS+i) != 0xff)
            goto Error;             //If error, break
    }
    P1 = 0xfc;                      //1111,1100 Erase successful
    Delay(10);                      //Delay
    for (i=0; i<512; i++)           //Program 512 bytes data into data flash
    {
        IapProgramByte(IAP_ADDRESS+i, (BYTE)i);
    }
    P1 = 0xf8;                      //1111,1000 Program successful
    Delay(10);                      //Delay
    for (i=0; i<512; i++)           //Verify 512 bytes data
    {
        if (IapReadByte(IAP_ADDRESS+i) != (BYTE)i)
            goto Error;             //If error, break
    }
    P1 = 0xf0;                      //1111,0000 Verify successful
    while (1);
Error:
    P1 &= 0x7f;                     //0xxx,xxxx IAP operation fail
    while (1);
}

/*----------------------------
Software delay function
----------------------------*/
void Delay(BYTE n)
{
    WORD x;

    while (n--)
    {
        x = 0;
        while (++x);
    }
}

/*----------------------------
Disable ISP/IAP/EEPROM function
Make MCU in a safe state
----------------------------*/
void IapIdle()
{
    IAP_CONTR = 0;                  //Close IAP function
    IAP_CMD = 0;                    //Clear command to standby
    IAP_TRIG = 0;                   //Clear trigger register
    IAP_ADDRH = 0x80;               //Data ptr point to non-EEPROM area
    IAP_ADDRL = 0;                  //Clear IAP address to prevent misuse
}

/*----------------------------
Read one byte from ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
Output:Flash data
----------------------------*/
BYTE IapReadByte(WORD addr)
{
    BYTE dat;                       //Data buffer

    IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
    IAP_CMD = CMD_READ;             //Set ISP/IAP/EEPROM READ command
    IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
    IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
    IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
    IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
    _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
    dat = IAP_DATA;                 //Read ISP/IAP/EEPROM data
    IapIdle();                      //Close ISP/IAP/EEPROM function

    return dat;                     //Return Flash data
}

/*----------------------------
Program one byte to ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
       dat (ISP/IAP/EEPROM data)
Output:-
----------------------------*/
void IapProgramByte(WORD addr, BYTE dat)
{
    IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
    IAP_CMD = CMD_PROGRAM;          //Set ISP/IAP/EEPROM PROGRAM command
    IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
    IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
    IAP_DATA = dat;                 //Write ISP/IAP/EEPROM data
    IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
    IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
    _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
    IapIdle();
}

/*----------------------------
Erase one sector area
Input: addr (ISP/IAP/EEPROM address)
Output:-
----------------------------*/
void IapEraseSector(WORD addr)
{
    IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
    IAP_CMD = CMD_ERASE;            //Set ISP/IAP/EEPROM ERASE command
    IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
    IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
    IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
    IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
    _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
    IapIdle();
}

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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