lier378912453 发表于 2024-5-22 06:20:58

EEPROM 无法存储问题 | 已解决

本帖最后由 32位8051-STCAI 于 2024-5-28 13:33 编辑



使用芯片及设置如上图;
目前状态是数据无法存储,代码如下

void update_eeprom_passwd()         //参照论坛例程
{
      EEPROM_SectorErase(0);
      EEPROM_write_n(0                     //写入的起始地址
                              , (void*)&man_data.passwd                   //buf数据存放的起始地址
                              , sizeof(man_data.passwd));    //
}


u8 update_admin_passwd(u8 buf[],u8 len)
{
      if(in_len == 0)
      {
                for(i=0;i<len;i++)
                {
                        old_key = buf;
                }
                in_len = len;
               
          TX1_write2buff(i%10+'0'); //测试用               
                return 1;
      }
      return 0;
}
//****************************************************
u8 update_admin_passwd1(u8 buf[],u8 len)
{      
/************************************************************************/      
      if(in_len != len)//第二次输入长度不对
      {
                PrintString1("erci changdu ng\n\r");
                return 0;//返回错误。
      }
      
      for(i=0;i<len;i++)
      {
                if(old_key != buf)
                {
                        PrintString1("erci shuju ng\n\r");
                        return 0;   //返回错误,第一次和第二次输入的不一致
                }
      }
      
      in_len = 0;    //输入正确,清零全局变量。               
      for(i=0;i<len;i++)
      {
                man_data.passwd = buf;
      }
      man_data.passwd_len = len;
      for(;i<6;i++)
      {
                man_data.passwd = 0xff;
      }
      delay_ms(20);
      update_eeprom_passwd();
      PrintString1("123123\n\r");
      return 1;
/************************************************************************/               
}


lier378912453 发表于 2024-5-22 06:25:03

zhange 发表于 2024-5-22 07:32:06

lier378912453 发表于 2024-5-22 06:25


把程序发上来这样没法看   

lier378912453 发表于 2024-5-22 09:13:02

/******************************************************************/
#include        "eeprom.h"
/******************************************************************/
void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                              //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

/********************************************************
读单片机EEPROM
********************************************************/
staticu8 read_eeprom(u16 addr)
{
    u8 dat;

    IAP_CONTR = WT_20M;                         //使能IAP
    IAP_CMD = 1;                              //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                           //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

/********************************************************
单片机EEPROM扇区擦除
********************************************************/
void erase_eeprom(u16 addr)
{
    IAP_CONTR = WT_20M;                         //使能IAP
    IAP_CMD = 3;                              //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
                _nop_();
                _nop_();       
    IapIdle();
}

/******************************************************************/
// void DisableEEPROM(void)
/******************************************************************/
void DisableEEPROM(void)         //禁止IAP操作
{
        IAP_CONTR = 0;         //禁止IAP操作
        IAP_CMD   = 0;         //去除IAP命令
        IAP_TRIG= 0;         //防止IAP命令误触发
//        IAP_ADDRH = 0xff;      //清0地址高字节
//        IAP_ADDRL = 0xff;      //清0地址低字节,指向非EEPROM区,防止误操作
        IAP_ADDRH = 0x80;      //清0地址高字节
        IAP_ADDRL = 0;         //清0地址低字节,指向非EEPROM区,防止误操作
}
/******************************************************************/
// void EEPROM_Trig(void)
/******************************************************************/
void EEPROM_Trig(void)   //触发EEPROM
{
        F0 = EA;    //保存全局中断
        EA = 0;   //禁止中断, 避免触发命令无效
        IAP_TRIG = 0x5A; //先送5AH,再送A5H到IAP触发寄存器,每次都需要如此
        IAP_TRIG = 0xA5; //送完A5H后,IAP命令立即被触发启动//CPU等待IAP完成后,才会继续执行程序。
        _nop_();
        _nop_();        
        _nop_();   //3个空指令等待一下
        EA = F0;    //恢复全局中断
}

/******************************************************************/
// void EEPROM_read_n(EE_address,*DataAddress,number)
// 参数: EE_address:读取EEPROM的首地址.
// DataAddress:   读取数据后给到 数组首地址.
// number:          读取的字节长度.
/******************************************************************/

void EEPROM_read_n(unsigned int EE_address,unsigned char *DataAddress,unsigned int number)
{
        IAP_ENABLE(); //设置等待时间,允许IAP操作,送一次就够
        IAP_CMD = 1;//=1读;送字节读命令,命令不需改变时,不需重新送命令
        do
        {
                IAP_ADDRH = EE_address / 256;//送地址高字节(地址需要改变时才需重新送地址)
                IAP_ADDRL = EE_address % 256; //送地址低字节
                EEPROM_Trig(); //触发EEPROM操作
                *DataAddress = IAP_DATA;//读出的数据送往
                EE_address++;
                DataAddress++;
        }
        while(--number);
        DisableEEPROM();
}
/******************************************************************/
// void EEPROM_SectorErase(unsigned int EE_address)
/******************************************************************/
void EEPROM_SectorErase(unsigned int EE_address)
{
       IAP_ENABLE();//设置等待时间,允许IAP操作,送一次就够
       IAP_CMD = 3;//宏调用, =3,送扇区擦除命令,命令不需改变时,不需重新送命令
       IAP_ADDRH = EE_address / 256; //送扇区地址高字节(地址需要改变时才需重新送地址)
       IAP_ADDRL = EE_address % 256;//送扇区地址低字节
       EEPROM_Trig();//触发EEPROM操作
                _nop_();
                _nop_();
                _nop_();       
                _nop_();
       DisableEEPROM();//禁止EEPROM操作
}
/******************************************************************/
//EEPROM_write_n(EE_address,*DataAddress,number)
/**********************z********************************************/
// 参数: EE_address:写入EEPROM的首地址.
// DataAddress: 写入源数据的缓冲的首地址. 就是从数组读取数据,
// number:写入的字节长度.

void EEPROM_write_n(unsigned int EE_address,unsigned char *DataAddress,unsigned int number)
{
IAP_ENABLE(); //设置等待时间,允许IAP操作,送一次就够
IAP_CMD = 2;//宏调用, =2,送字节写命令
do
{
       IAP_ADDRH = EE_address / 256; //送地址高字节(地址需要改变时才需重新送地址)
       IAP_ADDRL = EE_address % 256;//送地址低字节
       IAP_DATA= *DataAddress;//送数据到IAP_DATA,只有数据改变时才需重新送
       EEPROM_Trig();//触发EEPROM操作
       _nop_();
       _nop_();
       _nop_();
       EE_address++;//下一个地址
       DataAddress++;//下一个数据
}
while(--number);//直到结束
DisableEEPROM();
}

乘风飞扬 发表于 2024-5-22 09:16:21

直接烧录附件例子到芯片里试试

lier378912453 发表于 2024-5-22 09:18:33

通过设定的数值,与新按键的数值进行二次对比,相同就保存
#include "bijiao.h"

static u8 old_key;
static u8 in_len = 0;       
u8 i;
//#define BLOCK_PASS_TOTAL 80   //每个块密码存放的用户数

static U_ManageDataman_data = {{0,0,0,0,0,0},{3,4,5,3,4,5},{1,1,2,2,3,3},{0xff,0xff,0xff,0xff},6,6,6};
/******************************************************/

/******************************************************/
void update_eeprom_passwd()
{
        EEPROM_SectorErase(0);
        EEPROM_write_n(0                     //写入的起始地址
                                , (void*)&man_data.passwd                   //buf数据存放的起始地址
                                , sizeof(man_data.passwd));    //
}
/******************************************************/

/*
        更新系统的密码,这里需要输入两次密码,第一次做保存使用。
*/
u8 update_admin_passwd(u8 buf[],u8 len)
{
        if(in_len == 0)
        {
                for(i=0;i<len;i++)
                {
                        old_key = buf;
                }
                in_len = len;
               
          TX1_write2buff(i%10+'0'); //测试用               
                return 1;
        }
        return 0;
}
//****************************************************
u8 update_admin_passwd1(u8 buf[],u8 len)
{       
/************************************************************************/       
        if(in_len != len)//第二次输入长度不对
        {
                PrintString1("erci changdu ng\n\r");
                return 0;//返回错误。
        }
       
        for(i=0;i<len;i++)
        {
                if(old_key != buf)
                {
                        PrintString1("erci shuju ng\n\r");
                        return 0;   //返回错误,第一次和第二次输入的不一致
                }
        }
       
        in_len = 0;    //输入正确,清零全局变量。               
        for(i=0;i<len;i++)
        {
                man_data.passwd = buf;
        }
        man_data.passwd_len = len;
        for(;i<6;i++)
        {
                man_data.passwd = 0xff;
        }
        delay_ms(20);
        update_eeprom_passwd();
        PrintString1("123123\n\r");
        return 1;
/************************************************************************/               
}

lier378912453 发表于 2024-5-22 09:39:26

用大佬给的例程 可以进行擦除读写,如图

lier378912453 发表于 2024-5-23 09:08:10

自己的例程 eeprom不能保存数据,各位大佬 这个存在哪些问题

电子DIY小家 发表于 2024-5-23 11:50:32

lier378912453 发表于 2024-5-23 09:08
自己的例程 eeprom不能保存数据,各位大佬 这个存在哪些问题

示例代码都测试通过了,直接示例代码上修改自己想要的功能不就好了

lier378912453 发表于 2024-5-26 10:48:32

各位大佬在咨询下 ,
根据ISP 下载软件给 STC8H4k64TL分配2K的EEPROM 空间,
eeprom地址是从000--511 第一扇区,512--1023 第二扇区.....这样来区分吗
页: [1] 2 3
查看完整版本: EEPROM 无法存储问题 | 已解决