sindge 发表于 2025-7-18 16:13:57

求助:IAP15W4K58s读写EEPROM失效

大神们,我用STC15库函数写IAP15W4K58s的EEPROM,好像写不进去.请各位大神帮我看下.另外库函数STC15FXXXX.H里的
#define         ISP_TRIG()        ISP_TRIG = 0x5A,        ISP_TRIG = 0xA5        其中的逗号是不是应该为分号?       




//========================================================================
void ReadParaFromEprom(void)
{
    EEPROM_read_n(EPROMSetParatAdd,EpromRecordData,SizeOfRecord);                     
    SetParaStructure.Unit=(((EpromRecordData>=Unit_gf)&&(EpromRecordData<=Unit_N ))?EpromRecordData:SetParaInit.Unit);      
    SetParaStructure.WireFactor=(((EpromRecordData>=0)&&(EpromRecordData<=20 ))?EpromRecordData:SetParaInit.WireFactor);   
    SetParaStructure.CloseTime=(((((u16)EpromRecordData<<8|(u16)EpromRecordData)>=0)&&(((u16)EpromRecordData<<8|(u16)EpromRecordData)<=3600))?((u16)EpromRecordData<<8|(u16)EpromRecordData):SetParaInit.CloseTime);   
    SetParaStructure.Sensitive=(((((u16)EpromRecordData<<8|(u16)EpromRecordData)>=100)&&(((u16)EpromRecordData<<8|(u16)EpromRecordData)<=2000))?((u16)EpromRecordData<<8|(u16)EpromRecordData):SetParaInit.Sensitive);   
    SetParaStructure.FlashSpeed=(((((u16)EpromRecordData<<8|(u16)EpromRecordData)>=500)&&(((u16)EpromRecordData<<8|(u16)EpromRecordData)<=5000))?((u16)EpromRecordData<<8|(u16)EpromRecordData):SetParaInit.FlashSpeed);   
    SetParaStructure.LastSaveNum=(((((u16)EpromRecordData<<8|(u16)EpromRecordData)>=0)&&(((u16)EpromRecordData<<8|(u16)EpromRecordData)<=127))?((u16)EpromRecordData<<8|(u16)EpromRecordData):SetParaInit.LastSaveNum);
}


//========================================================================
void WritePara2Eprom(void)
{
    EEPROM_read_n(EPROMStartAdd ,EpromSectionData,SizeOfSection);                  
    EEPROM_SectorErase(EPROMStartAdd);                                    
    EpromSectionData=SetParaStructure.Unit;
    EpromSectionData=SetParaStructure.WireFactor;
    EpromSectionData=SetParaStructure.CloseTime>>8;
    EpromSectionData=SetParaStructure.CloseTime;
    EpromSectionData=SetParaStructure.Sensitive>>8;
    EpromSectionData=SetParaStructure.Sensitive;
    EpromSectionData=SetParaStructure.FlashSpeed>>8;
    EpromSectionData=SetParaStructure.FlashSpeed;
    EpromSectionData=SetParaStructure.LastSaveNum>>8;
    EpromSectionData=SetParaStructure.LastSaveNum;
    EEPROM_write_n(EPROMStartAdd,EpromSectionData,SizeOfSection);         
}


相关的库函数如下:

//========================================================================
void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
{
        EA = 0;                //½ûÖ¹ÖжÏ

        ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);        //ÉèÖõȴýʱ¼ä£¬ÔÊÐíISP/IAP²Ù×÷£¬ËÍÒ»´Î¾Í¹»
        ISP_WRITE();                                                        //ËÍ×Ö½ÚдÃüÁÃüÁî²»Ðè¸Ä±äʱ£¬²»ÐèÖØÐÂËÍÃüÁî
        do
        {
                ISP_ADDRH = EE_address / 256;                //Ë͵ØÖ·¸ß×Ö½Ú£¨µØÖ·ÐèÒª¸Ä±äʱ²ÅÐèÖØÐÂË͵ØÖ·£©
                ISP_ADDRL = EE_address % 256;                //Ë͵ØÖ·µÍ×Ö½Ú
                ISP_DATA= *DataAddress;                        //ËÍÊý¾Ýµ½ISP_DATA£¬Ö»ÓÐÊý¾Ý¸Ä±äʱ²ÅÐèÖØÐÂËÍ
                //ISP_TRIG();
      ISP_TRIG = 0x5A;
      ISP_TRIG = 0xA5;
                _nop_();
      _nop_();
      _nop_();
      _nop_();
                EE_address++;
                DataAddress++;
        }while(--number);

        DisableEEPROM();
        EA = 1;                //ÖØÐÂÔÊÐíÖжÏ
}




//========================================================================
void EEPROM_SectorErase(u16 EE_address)
{
        EA = 0;                //½ûÖ¹ÖжÏ
                                                                                        //Ö»ÓÐÉÈÇø²Á³ý£¬Ã»ÓÐ×Ö½Ú²Á³ý£¬512×Ö½Ú/ÉÈÇø¡£
                                                                                        //ÉÈÇøÖÐÈÎÒâÒ»¸ö×Ö½ÚµØÖ·¶¼ÊÇÉÈÇøµØÖ·¡£
        ISP_ADDRH = EE_address / 256;                        //ËÍÉÈÇøµØÖ·¸ß×Ö½Ú£¨µØÖ·ÐèÒª¸Ä±äʱ²ÅÐèÖØÐÂË͵ØÖ·£©
        ISP_ADDRL = EE_address % 256;                        //ËÍÉÈÇøµØÖ·µÍ×Ö½Ú
        ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);        //ÉèÖõȴýʱ¼ä£¬ÔÊÐíISP/IAP²Ù×÷£¬ËÍÒ»´Î¾Í¹»
        ISP_ERASE();                                                        //ËÍÉÈÇø²Á³ýÃüÁÃüÁî²»Ðè¸Ä±äʱ£¬²»ÐèÖØÐÂËÍÃüÁî
        //ISP_TRIG();
    ISP_TRIG = 0x5A;
    ISP_TRIG = 0xA5;
        _nop_();
    _nop_();
    _nop_();
    _nop_();
        DisableEEPROM();
        EA = 1;                //ÖØÐÂÔÊÐíÖжÏ
}




//========================================================================

void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
{
        EA = 0;                //½ûÖ¹ÖжÏ
        ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);        //ÉèÖõȴýʱ¼ä£¬ÔÊÐíISP/IAP²Ù×÷£¬ËÍÒ»´Î¾Í¹»
        ISP_READ();                                                                        //ËÍ×Ö½Ú¶ÁÃüÁÃüÁî²»Ðè¸Ä±äʱ£¬²»ÐèÖØÐÂËÍÃüÁî
        do
        {
                ISP_ADDRH = EE_address / 256;                //Ë͵ØÖ·¸ß×Ö½Ú£¨µØÖ·ÐèÒª¸Ä±äʱ²ÅÐèÖØÐÂË͵ØÖ·£©
                ISP_ADDRL = EE_address % 256;                //Ë͵ØÖ·µÍ×Ö½Ú
//                ISP_TRIG();                                                        //ÏÈËÍ5AH£¬ÔÙËÍA5Hµ½ISP/IAP´¥·¢¼Ä´æÆ÷£¬Ã¿´Î¶¼ÐèÒªÈç´Ë
//                                                                                        //ËÍÍêA5Hºó£¬ISP/IAPÃüÁîÁ¢¼´±»´¥·¢Æô¶¯
//                                                                                        //CPUµÈ´ýIAPÍê³Éºó£¬²Å»á¼ÌÐøÖ´ÐгÌÐò¡£
      ISP_TRIG = 0x5A;
      ISP_TRIG = 0xA5;
                _nop_();
      _nop_();
      _nop_();
      _nop_();
                *DataAddress = ISP_DATA;                        //¶Á³öµÄÊý¾ÝËÍÍù
                EE_address++;
                DataAddress++;
        }while(--number);

        DisableEEPROM();
        EA = 1;                //ÖØÐÂÔÊÐíÖжÏ
}



//========================================================================
void        DisableEEPROM(void)
{
        ISP_CONTR = 0;                        //½ûÖ¹ISP/IAP²Ù×÷
        ISP_CMD   = 0;                        //È¥³ýISP/IAPÃüÁî
        ISP_TRIG= 0;                        //·ÀÖ¹ISP/IAPÃüÁîÎó´¥·¢
        ISP_ADDRH = 0xff;                //Çå0µØÖ·¸ß×Ö½Ú
        ISP_ADDRL = 0xff;                //Çå0µØÖ·µÍ×Ö½Ú£¬Ö¸Ïò·ÇEEPROMÇø£¬·ÀÖ¹Îó²Ù×÷
}




sindge 发表于 2025-7-18 16:19:20

EEPRO读写地址如下:
#define   EPROMStartAdd         0xE000
#define   EPROMSetParatAdd      0xE000
#define   SizeOfSection         512
#define   SizeOfRecord            16

sindge 发表于 2025-7-18 16:29:11

您好,您回复的:
1.需确认EPROMSetParatAdd是有效的EEPROM地址(通常为0x0000~0x07FF),且SizeOfRecord不超过单次写入限制(一般为16字节)。IAP15W4K58S有效的EEPROM地址应该为:0x0000~0xE7FF吧.另外单次写入限制为什么只有16个字节?
2.建议使用轮询方式等待ISPFLAG标志位:IAP15W4K58S有ISPFLAG标志位吗?

DebugLab 发表于 2025-7-18 17:52:31

EEPROM程序供参考:

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)
{
        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();
}

DebugLab 发表于 2025-7-18 19:07:34

应该是分号
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;

DebugLab 发表于 2025-7-18 19:16:15

sindge 发表于 2025-7-18 16:19
EEPRO读写地址如下:
#define   EPROMStartAdd         0xE000
#define   EPROMSetParatAdd      0xE00 ...

总大小0xE800,0xE000也没有超出范围,使用的是倒数第4个扇区,地址没有问题

sindge 发表于 2025-7-22 14:40:19

测试时发现,仿真时读EEPROM可以,但是写EEPROM时序好像就乱了
页: [1]
查看完整版本: 求助:IAP15W4K58s读写EEPROM失效