[STC单片机] 自带EEPROM怎么停电后丢失

[复制链接]
 楼主| 孟新辉 发表于 2016-4-22 16:53 | 显示全部楼层 |阅读模式
#ifndef _EEPROM_H_
#define _EEPROM_H_

#include<STC15W408AS.h>

#define u16 unsigned int
#define u8  unsigned char

//STCµ¥Æ¬»úIAP¶¨Òå

//sfr IAP_DATA=0xC2;
//sfr IAP_ADDRH=0xC3;
//sfr IAP_ADDRL=0xC4;
//sfr IAP_CMD=0xC5;
//sfr IAP_TRIG=0xC6;
//sfr IAP_CONTR=0xC7;

#define ISP_IAP_BYTE_READ 1   //×Ö½Ú¶Á¡
#define ISP_IAP_BYTE_PROGRAM 2//×Ö½Ú±à³Ì
#define ISP_IAP_SECTOR_ERASE 3//ÉÈÇø²Á³ý
#define WAIT_TIME 0//µÈ´ýʱ¼ä
#define ENABLE_IAP 0x82

u8 Read_IAP(u16 Adres);
extern void Write_IAP(u8 Value,u16 Adres);
extern void Sector_Erase_IAP(u16 Sector);
extern void DISAble_IAP(void);

#endif


#include"eeprom.h"
#include <intrins.h>       

//IAP´¦Àí²¿·Ö¿ªÊ¼

//¹Ø±ÕIAP¹¦ÄÜ

void Disable_IAP(void)
{
  IAP_CONTR=0;
  IAP_CMD=0;
  IAP_TRIG=0;
  IAP_ADDRH=0x80;
  IAP_ADDRL=0x00;
}

//¶ÁÈ¡IAPÊý¾Ý²¢·µ»Ø
//ADRES=ÐèÒª¶Á³öÊý¾ÝµÄµØÖ·
//µ÷Ó㺹رÕIAP¹¦Äܺ¯Êý

u8 Read_IAP(u16 Adres)
{
  u8 Value=0;
  IAP_CONTR=ENABLE_IAP;//´ò¿ªIAP¹¦ÄÜ
  IAP_CMD=ISP_IAP_BYTE_READ;//¶ÁIAP
        IAP_ADDRL=Adres;//È¡µÍλµØÖ·
  IAP_ADDRH=Adres>>8;//È¡¸ßλµØÖ·
  EA=0;//¹ØÖжÏ
  IAP_TRIG=0x5A;//´¥·¢¼Ä´æÆ÷
  IAP_TRIG=0xA5;//IAP´¥·¢Æô¶¯
  _nop_();
  Value=IAP_DATA;//¶ÁÈ¡×Ö½ÚÊý¾Ý
  EA=1;
  Disable_IAP();//¹Ø±ÕIAP¹¦ÄÜ
  return Value;
}

//×Ö½Ú±à³Ì
//value=ÐèҪд½øIAPÄÚ²¿µÄÊý¾Ý
//adres=ÐèҪдÈëÊý¾ÝµÄµØÖ·
//µ÷ÓùرÕIAP¹¦Äܺ¯Êý
void Write_IAP(u8 Value,u16 Adres)
{
  IAP_CONTR=ENABLE_IAP;//´ò¿ªIAP¹¦ÄÜ
  IAP_CMD=ISP_IAP_BYTE_PROGRAM;//×Ö½Ú±à³Ì
        IAP_ADDRL=Adres;
  IAP_ADDRH=Adres>>8;//È¡µØÖ·Î»
  IAP_DATA=Value;//дÈëÊý¾Ý
  EA=0;
  IAP_TRIG=0x5A;  //´¥·¢IAP¹¦ÄÜ
  IAP_TRIG=0xA5;
  _nop_();
  EA=1;
  Disable_IAP();//¹Ø±ÕIAP¹¦ÄÜ
}

//²Á³ýÉÈÇø¹¦ÄÜ
//Sector=ÐèÒª²Á³ýµÄÉÈÇøµØÖ·
//µ÷Óú¯Êý£º¹Ø±ÕIAP¹¦Äܺ¯Êý
void Sector_Erase_IAP(u16 Sector)
{
  IAP_CONTR=ENABLE_IAP;
  IAP_CMD=ISP_IAP_SECTOR_ERASE;
        IAP_ADDRL=Sector;
  IAP_ADDRH=Sector>>8;
  EA=0;
  IAP_TRIG=0x5A;
  IAP_TRIG=0xA5;
  _nop_();
  EA=1;
  Disable_IAP();
}

主函数里关于这个部分:
js=Read_IAP(0x3000);
                        delayms(10);
                        js++;
                        Sector_Erase_IAP(0x3000);
                        delayms(10);
            Write_IAP(js,0x3000);
                        delayms(10);
                        js1=Read_IAP(0x3000);
        senddata(js1);
搞了一天没搞定啊   大侠们帮我看看问题在哪啊   MCU是STC15W408AS    停电后  数据从0开始,按道理应该接着后边啊。证明没有保存进去。
armxu 发表于 2016-4-28 09:00 | 显示全部楼层
你到STC官网下库程序,那里有EEPROM的库文件,用起来很方便。不过我觉得还是用铁电比较好,STC是用FLASH模拟EEPROM,主要擦除数据最快也要21ms,铁电就很快。
armxu 发表于 2016-4-28 09:03 | 显示全部楼层
我的铁电程序如下,你可以参考下结构,擦除语句不能放在while()前面,那样每次开机都会擦除数据,也就无法保存数据了。
void main(void)
{       
  init_NRF24L01(); //初始化NRF2401L
    Delay_ms(10);                                 //等待HC595上电稳定
        //Timer0_Init();                             //定时器0初始化
         INT0_Init();          //外部中断0初始化
          HC595_Init();                                 //HC595锁存器初始化
          UART_config();     //串口初始化
   sendBuf[0]=2;        //确定需要2.4G发送的数据个数,与上海宝嵌的模块有关
            cnt=readbyte(0);//从铁电读取数据
   Dotcnt=readbyte(1);//从铁电读取数据
       
  
          while(1)
        {       
                           
                 FourLedDisplayBuf(cnt,Dotcnt);
                  LED_Display(); //数码管显示
  // if((EnableSaveFlag==1)&&((Oldcnt==cnt)&&(OldDotcnt==Dotcnt))&&(MainLoopCount==160))
   if((EnableSaveFlag==1)        )         
         {
                 EnableSaveFlag=0;
                 EA=0;
                 writebyte(0,cnt);   //数据写入铁电
                 writebyte(1,Dotcnt);//数据写入铁电
                 TX1_write2buff(cnt);//串口发送cnt
                 TX1_write2buff(Dotcnt);//串口发送Dotcnt
                 sendBuf[2]=Dotcnt;
           sendBuf[1]=cnt;          
           nRF24L01_TxPacket(sendBuf);
                         EA=1;               
         }
   
        }
       
}
ywlzh 发表于 2016-4-28 09:38 | 显示全部楼层
首先你程序要对EEPROM 能读能写

然后是完善的问题
一个笨拙的办法:就是你要存的数据,这些个参数一旦有变化你就往EEPROM里存,上电读就是了
一个比较完善的方法,你在单片机的附近加上一个放电延时的电路,再配合ADC,一旦检测到电源值到了危险值了,ADC中断,存数据。其他外设该关就关了吧
NE5532 发表于 2016-4-28 10:40 | 显示全部楼层
你先确认不掉电的情况下,数据确实写进去了。另外上电以后,要等电源稳定了,才能操作E2,不然就要掉数据,做个小延时。
ningling_21 发表于 2016-4-28 11:50 | 显示全部楼层
armxu 发表于 2016-4-28 09:03
我的铁电程序如下,你可以参考下结构,擦除语句不能放在while()前面,那样每次开机都会擦除数据,也就无法 ...

确保地址没超出范围+足够延时
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

3

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部