使用eeprom时写入无返回错误,但读不出数据
<p>各位大佬先且看我的代码和log打印</p><pre><code class="language-c">#define CMD_IDLE 0 //空闲模式
#define CMD_READ 1 //IAP字节读命令
#define CMD_PROGRAM 2 //IAP字节编程命令
#define CMD_ERASE 3 //IAP扇区擦除命令
#define ENABLE_IAP 0x80 //if SYSCLK<30MHz
#define IAP_TPS_CONSTANT ((FOSC/1000000)+1)
static const unsigned long iapTps = IAP_TPS_CONSTANT;
//********************关闭IAP*******************************ok
static void IapIdle()
{
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP区域
IAP_ADDRL = 0;
}
//************************从ISP/IAP/EEPROM区域读取一字节****************************ok
static BYTE IapReadByte(WORD addr)
{
BYTE dat; //数据缓冲区
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_TPS = iapTps; //设置等待参数 ********************************************STC8C2K64S2
IAP_CMD = CMD_READ; //设置IAP命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
dat = IAP_DATA; //读ISP/IAP/EEPROM数据
IapIdle(); //关闭IAP功能
return dat; //返回
}
//*********写一字节数据到ISP/IAP/EEPROM区域*************************************ok
static BYTE IapProgramByte(WORD addr, BYTE dat)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_TPS = iapTps; //设置等待参数 ********************************************STC8C2K64S2
IAP_CMD = CMD_PROGRAM; //设置IAP命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_DATA = dat; //写ISP/IAP/EEPROM数据
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
IapIdle(); //关闭IAP功能
return FIND_BIT(IAP_CONTR, 4);
}
//**************************************扇区擦除************************************ok
static BYTE IapEraseSector(WORD addr)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_ERASE; //设置IAP命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
IapIdle(); //关闭IAP功能
return FIND_BIT(IAP_CONTR, 4);
}
BYTE* eepRom_Read_DevAddr(void)
{
unsigned char cnt;
const unsigned char DevIdLen = EEPROM_DEVID_END_ADDR - EEPROM_DEVID_START_ADDR;
memset(eepRomBuffer, 0, sizeof(eepRomBuffer));
for ( cnt = 0; cnt < DevIdLen; cnt++ )
eepRomBuffer = IapReadByte(EEPROM_DEVID_START_ADDR + cnt);
return eepRomBuffer;
}
int eepRom_Save_DeviceAddress(const char* DevId)
{
unsigned char cnt = 0;
BYTE Flag_QRcodeShow = 0;
const int DevIdLen = EEPROM_DEVID_END_ADDR - EEPROM_DEVID_START_ADDR;
if ( *(DevId + DevIdLen) != '\0' || DevId == NULL )
return EEPROM_ERR_ARG; // 没有结束符或参数为NULL
Flag_QRcodeShow = IapReadByte((WORD)EEPROM_QRCODE_FLAG_ADDR);
DebugPrint(TAG, "frist, save QRcode flag: %bu", Flag_QRcodeShow);
if ( IapEraseSector(IAP_ADDRESS2) )
goto _EEPROM_ERR;
DebugPrint(TAG, "erase successes... will write data: %s", DevId);
for ( cnt = 0; cnt < DevIdLen; cnt++ )
{
if ( IapProgramByte((WORD)(IAP_ADDRESS2 + cnt), (BYTE)(*(DevId + cnt))) )
{
DebugPrint(TAG, "write eepRom error");
goto _EEPROM_ERR;
}
}
IapProgramByte((WORD)EEPROM_QRCODE_FLAG_ADDR, Flag_QRcodeShow);
DebugPrint(TAG, "save data..");
DebugPrint(TAG, "write data: %s", eepRom_Read_DevAddr());
return (strcmp(DevId, eepRomBuffer) == 0) ? EEPROM_OK : EEPROM_FAIL;
_EEPROM_ERR:
CLEAR_BIT(IAP_CONTR, 4); // 清除IAP错误
return (int)IapEraseSector(IAP_ADDRESS2);
}
</code></pre>
<h4>正是这么一段代码,但打印出了以下log</h4>
<pre><code class="language-text"> ----bufAddr status (ok), len 108 from UART2:
id.a001...a001
----send to UART1
bufAddr:x:0689, bufferLen:0
:funcString: id
:into command 'ID'
:print DevID
:frist, save QRcode flag: 0
:erase successes... will write data: a001
:save data..
:write data:
:save DevId status: fail
</code></pre>
<p>我一开始以为是没接收到数据,但并不是接收不到数据。我怀疑是数据根本就没有写入,但为什么会出现这种情况呢?若写入有报错了,我的代码应当返回错误值而不是继续写。还有,根据手册上的描述,<code> IAP_TPS</code>是一个等待时间控制寄存器,故此<code>_nop_()</code>函数是必要的吗?能否用自定义的定时器延时函数替代?</p>
<p>在11.0592MHz的时候能正常写入<br />
在27MHz的时候就没写进去</p>
<p><img alt="penxue" class="emoji" src="https://www.stcaimcu.com/static/image/smiley/default/penxue.gif" title="penxue" /></p>
<p>希望来个大佬为我答疑解惑🙏🙏🙏</p>
<h1>有点玄学了。。。</h1>
<p>从11.0592MHz试过OK以后,我将频率逐渐提升到33.1776MHz也写入正常了<img alt="yiwen" class="emoji" src="https://www.stcaimcu.com/static/image/smiley/default/yiwen.gif" title="yiwen" /></p>
<p>我一时间分辨不清楚,是真的能写了还是只有这个能写了。。。</p>
_nop_()函数是必要的 void Iap_Idle(void)
{
IAP_CONTR&=~IAPEN;
IAP_CMD=IAP_IDL;
IAP_TRIG=0x00;
IAP_ADDRH=0x80;
IAP_ADDRL=0x00;
}
unsigned char Iap_Read_Byte(unsigned char sector,unsigned int addr)
{
return *(CBYTE+IAP_OFFSET+sector*0x0200+addr);
}
//unsigned char Iap_Read_Byte(unsigned char sector,unsigned int addr)
//{
// unsigned char dat;
// unsigned int add;
// add=sector*0x0200+addr;
// IAP_CONTR|=IAPEN;
// IAP_TPS=IAP_TPS_;
// IAP_CMD=IAP_READ;
// IAP_ADDRL=add;
// IAP_ADDRH=add>>8;
// IAP_TRIG=0x5A;
// IAP_TRIG=0xA5;
// _nop_();
// dat=IAP_DATA;
// Iap_Idle();
// return dat;
//}
void Iap_Program_Byte(unsigned char sector,unsigned int addr,unsigned char dat)
{
unsigned int add;
add=sector*0x0200+addr;
IAP_CONTR|=IAPEN;
IAP_TPS=IAP_TPS_;
IAP_CMD=IAP_WRITE;
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_DATA=dat;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
_nop_();
Iap_Idle();
}
void Iap_Erase_Sector(unsigned char sector)
{
unsigned int add;
add=sector*0x0200;
IAP_CONTR|=IAPEN;
IAP_TPS=IAP_TPS_;
IAP_CMD=IAP_ERASE;
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
_nop_();
Iap_Idle();
}
页:
[1]