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
把程序发上来这样没法看 /******************************************************************/
#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();
} 直接烧录附件例子到芯片里试试 通过设定的数值,与新按键的数值进行二次对比,相同就保存
#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;
/************************************************************************/
} 用大佬给的例程 可以进行擦除读写,如图 自己的例程 eeprom不能保存数据,各位大佬 这个存在哪些问题 lier378912453 发表于 2024-5-23 09:08
自己的例程 eeprom不能保存数据,各位大佬 这个存在哪些问题
示例代码都测试通过了,直接示例代码上修改自己想要的功能不就好了 各位大佬在咨询下 ,
根据ISP 下载软件给 STC8H4k64TL分配2K的EEPROM 空间,
eeprom地址是从000--511 第一扇区,512--1023 第二扇区.....这样来区分吗