王锦平 发表于 2025-2-28 01:05:04

使用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&lt;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 &gt;&gt; 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 &gt;&gt; 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 &gt;&gt; 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 &lt; 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, &quot;frist, save QRcode flag: %bu&quot;, Flag_QRcodeShow);

    if ( IapEraseSector(IAP_ADDRESS2) )
      goto _EEPROM_ERR;

    DebugPrint(TAG, &quot;erase successes... will write data: %s&quot;, DevId);
    for ( cnt = 0; cnt &lt; DevIdLen; cnt++ )
    {
      if ( IapProgramByte((WORD)(IAP_ADDRESS2 + cnt), (BYTE)(*(DevId + cnt))) )
      {
            DebugPrint(TAG, &quot;write eepRom error&quot;);
            goto _EEPROM_ERR;
      }

    }
    IapProgramByte((WORD)EEPROM_QRCODE_FLAG_ADDR, Flag_QRcodeShow);
    DebugPrint(TAG, &quot;save data..&quot;);

    DebugPrint(TAG, &quot;write data: %s&quot;, 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>

王锦平 发表于 2025-2-28 01:09:58

<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>

王锦平 发表于 2025-2-28 01:10:28

<p>希望来个大佬为我答疑解惑🙏🙏🙏</p>

王锦平 发表于 2025-2-28 01:23:02

<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>

DebugLab 发表于 2025-2-28 06:46:05

_nop_()函数是必要的

DebugLab 发表于 2025-2-28 06:47:32

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]
查看完整版本: 使用eeprom时写入无返回错误,但读不出数据