找回密码
 立即注册
查看: 605|回复: 5

读取STC32G8K64中的EEPROM时,错位了一个字节

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-06-07 15:56:13

2

主题

2

回帖

44

积分

新手上路

积分
44
发表于 2024-6-6 15:34:30 | 显示全部楼层 |阅读模式
最近在做一个项目,使用的STC的STC32G8K64芯片, EEPROM部分是从另外一个项目移过来的, 修改时,EEPROM部分读琮时好时错,
即在EEPROM部分的文件不改动的情况下,有时EEPROM是对的, 有时是错的,甚至更改KEIL的编译选项时,也会出现对错。
当出现错误时,通过串口把数据送出来看,发现在读取数据时,数据串的前面多了一个0, 如读取40字节,第一个是多出来的0,后面的39字节是EEPROM中的前39个数据(数据是正确的,但错位了);
数据放在结构体中也就错了,CRC验证也错了;
在不改动EEPROM的情况下,只须改动别的文件,再编译,此部分又会正确,好像编译有关系。

读写操作时,关闭中断也没用。

大家有没有遇到这种情况?





void FLASH_SECTOR_ERASED(unsigned char flash_addrh)
{
           uchar        IE_TEMP=IE;
        if (flash_addrh >= 8)
        return;                //超出不擦除
    EA        =0;
        IAP_TPS = FOSC_TPS;
    IAP_CONTR        =0X80;       
    IAP_CMD        =3;                        //擦除 IAP_ADDRH       
        IAP_ADDRE  =0;
    IAP_ADDRH        =flash_addrh;
    IAP_ADDRL        =0;

    _nop_();
    IAP_TRIG        =0X5A;
//   _nop_();
  //  _nop_();
    IAP_TRIG        =0XA5;
    _nop_();

    IAP_CONTR        =0;
    IAP_CMD        =0;
    IAP_TRIG=0;
    IAP_ADDRH        =0;
        IE =IE_TEMP ;
}


/* 连续字节读
;入口:        FLASH_ADDRH,FLASH_ADDRL,R2,R0
;出口:        ips的Len个数据
;IAP_CMD,0=无操作,1=读,2=写,3=擦除
*/
void FLASH_byte_readS(const unsigned char *ips,unsigned short flash_add,unsigned char Len)
{
    uchar        IE_TEMP=IE;
        uchar        i;
        uchar        *IP8 =ips ;
        if ((flash_add >=0X400) )
        return        ;
    EA        =0;
    IAP_CONTR        =0X80;               
        IAP_TPS =FOSC_TPS;
    IAP_CMD        =1;                //读
        IAP_ADDRE  =0;
    IAP_ADDRH        =flash_add >>8;
    IAP_ADDRL        =flash_add;


//   while (Len--)
        for (i =0; i < Len; i ++)
    {
         _nop_();
                   _nop_();
                IAP_TRIG        =0X5A;
    //    _nop_();
    //    _nop_();               
        IAP_TRIG        =0XA5;
        _nop_();                       
        *IP8        =IAP_DATA;        //取出数据
        IP8        ++;
        IAP_ADDRL++;
    }
  

    IAP_CONTR        =0;
    IAP_CMD        =0;
    IAP_TRIG=0;
    IAP_ADDRH        =0;
        IE =IE_TEMP ;
}



/*; 连续字节编程
;入口:        FLASH_ADDRH,FLASH_ADDRL,R2(个数),R0(RAM地址)
;出口:        写
;IAP_CMD,0=无操作,1=读,2=写,3=擦除

*/
void FLASH_byte_WRITES(const unsigned char *ips,unsigned short flash_add,unsigned char Len)
{
    uchar        IE_TEMP=IE;
        uchar        i;
        uchar        *IP8 =ips ;
        if ((flash_add>=0X400) )
        return;
    EA        =0;
    IAP_CONTR        =0X80;               
        IAP_TPS =FOSC_TPS;
    IAP_CMD        =2;                //写       
       
                IAP_ADDRE  =0x0;
    IAP_ADDRH        =flash_add >>8;
    IAP_ADDRL        =flash_add;

//    while (Len--)
        for (i =0; i < Len; i ++)
    {
                 _nop_();      
                IAP_DATA        =*IP8;        //送数据

        IAP_TRIG        =0X5A;
     //   _nop_();
        //        _nop_();
        IAP_TRIG        =0XA5;
        _nop_();
       
        IP8        ++;
        IAP_ADDRL++;
    }

   IAP_CONTR        =0;
    IAP_CMD        =0;
    IAP_TRIG=0;
    IAP_ADDRH        =0;
        IE =IE_TEMP ;
}



/***********************************************************/




void        StorParam_TEMP(uchar stor_addr)
{
        ushort        crc;

        if (stor_addr ==0 )
        {                //写第一页参数
                FLASH_SECTOR_ERASED(0);
               
//                LocalParam.Out_DA0 = 88;       
//                LocalParam.res1 = 66;                       
                crc = CRC_gen((uchar *)(&LocalParam), sizeof(LocalParam)-2);
                LocalParam.ParamVaildFlag = crc;
/*               
                        COPY_MEM( (uchar *)(&LocalParam),UartRxdBuf,sizeof(LocalParam) );
                USARTCB.TxdPackLength =sizeof(LocalParam) +2;       
                StartUartSend(UartRxdBuf);       
        F500MS_STA =0 ;
         while(F500MS_STA ==0);       
                 F500MS_STA =0 ;
         while(F500MS_STA ==0);
*/       
                FLASH_byte_WRITES((uchar *)(&LocalParam), SYS_PARAM_EEPROM_ADDR  ,  sizeof(LocalParam)  );        //存储系统参数
        //        F500MS_STA =0;       
        //        while(F500MS_STA ==0);
        //        F500MS_STA =0;               
        //        while(F500MS_STA ==0);               
               
                crc = CRC_gen((uchar *)(&CalParam), sizeof(CalParam)-2);
                CalParam.ParamVaildFlag = crc;               
                FLASH_byte_WRITES((uchar *) &CalParam.FULL_CUR_DA_VAL , CAL_PARAM_EEPROM_ADDR   ,   sizeof(CalParam) );        //存储系统参数               
               
               
        //        crc = CRC_gen((uchar *)(&LocalParam0), sizeof(LocalParam)-2);
        //        LocalParam0.ParamVaildFlag = crc;               
        //        FLASH_byte_WRITES((uchar *) &LocalParam0.Password, SYS_PARAM_EEPROM_ADDR0 ,  sizeof(LocalParam));//存储出厂系统参数

               
        }
        else
        {        //写第二页参数
                FLASH_SECTOR_ERASED(2);
                crc = CRC_gen((uchar *)(&LocalParam), sizeof(LocalParam)-2);
                LocalParam.ParamVaildFlag = crc;
                FLASH_byte_WRITES((uchar *)(&LocalParam), SYS_PARAM_EEPROM_ADDR1  ,  sizeof(LocalParam)  );        //存储系统参数
                crc = CRC_gen((uchar *)(&CalParam), sizeof(CalParam)-2);
                CalParam.ParamVaildFlag = crc;
                FLASH_byte_WRITES((uchar *) &CalParam.FULL_CUR_DA_VAL , CAL_PARAM_EEPROM_ADDR1   ,   sizeof(CalParam) );        //存储系统参数       
               
        }                       
}



/*
//void        Write_DS18B20_ID(void)
{
//        FLASH_WriteBlock(0X60, &DS18B20_RAM[0][0] , 16);
}
*/
/*********************************************************/
/*
        1有效,取第一组;1无效而2有效,取第2组;否则看第3组是否有效。都无效写默认值
        得到有效的,比较其他2组是否一样,如不一样则写,
        00~16,存储LocalParam数据,0X60~ 0X89存储出厂数据; 0X100 ~ 0X3A, 存储Cal_register数据, 0X160~ 0X19A存储出厂数据


*/


void        InitParam(void)
{
//        uchar        addr, i, j,,k;
//        uchar        *ip ;
        ushort        crc,CRC_TEMP;
        uchar        err=0;       


        FLASH_byte_readS((uchar *)(&LocalParam), SYS_PARAM_EEPROM_ADDR, sizeof(LocalParam) );       

               
        FLASH_byte_readS((uchar *)(&CalParam), CAL_PARAM_EEPROM_ADDR, sizeof(CalParam));               
//        return;
        crc = CRC_gen((uchar *)(&LocalParam), sizeof(LocalParam)-2);                       

/*        COPY_MEM( (uchar *)(&LocalParam),UartRxdBuf,sizeof(LocalParam) );       

        //UartRxdBuf[sizeof(LocalParam)+1] =crc >>8;
        //UartRxdBuf[sizeof(LocalParam)+2] =crc ;       
       
                USARTCB.TxdPackLength =sizeof(LocalParam) +4;       
                StartUartSend(UartRxdBuf);       
        F500MS_STA =0 ;
         while(F500MS_STA ==0);       
                 F500MS_STA =0 ;
         while(F500MS_STA ==0);               
        */       
        if (LocalParam.ParamVaildFlag != crc)

       {


        }
}




回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2024-6-7 11:06:41 | 显示全部楼层
先用附件例程烧到芯片进行测试,功能验证正常后再进行修改或者移植。

按键触发EEPROM读写测试程序-通过串口1输出-32G.zip

17.6 KB, 下载次数: 66

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-06-07 15:56:13

2

主题

2

回帖

44

积分

新手上路

积分
44
发表于 2024-6-7 15:54:16 | 显示全部楼层
谢谢了!
把触发子程序换掉,更换编译选项,没再发现出错,
可能是触发后的4个_NOP_有关系
(我的原来只有一个,前面的倒是有加NOP去测,就是没加后面的)。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2024-05-02 21:48:56

6

主题

48

回帖

614

积分

高级会员

积分
614
发表于 2024-6-9 15:05:08 | 显示全部楼层
xml*** 发表于 2024-6-7 15:54
谢谢了!
把触发子程序换掉,更换编译选项,没再发现出错,可能是触发后的4个_NOP_有关系(我的原来只有一 ...

我用STC8H2K08U也出现了这个问题.然后用单独EEPROM代码验证发现写入地址为0,2,4,8...就正常了.但在开ADC/PWM等代码之后还是不行,总是移位一个地址.现在我目前的案子只要写一个u8数据到Flash就暂时没有验证下去了.
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-06-07 15:56:13

2

主题

2

回帖

44

积分

新手上路

积分
44
发表于 2024-6-13 09:17:11 | 显示全部楼层
qq6035*** 发表于 2024-6-9 15:05
我用STC8H2K08U也出现了这个问题.然后用单独EEPROM代码验证发现写入地址为0,2,4,8...就正常了.但在开ADC/ ...

我就换了这一段
void EEPROM_Trig(void)
{
    F0 = EA;    //保存全局中断
    EA = 0;     //禁止中断, 避免触发命令无效
    IAP_TRIG = 0x5A;
    IAP_TRIG = 0xA5;                    //先送5AH,再送A5H到IAP触发寄存器,每次都需要如此
                                        //送完A5H后,IAP命令立即被触发启动
                                        //CPU等待IAP完成后,才会继续执行程序。
    _nop_();   //由于STC32G是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
    _nop_();
    _nop_();
    _nop_();
    EA = F0;    //恢复全局中断
}

即IAP_TRIG = 0xA5;  这个后面由一个_NOP_改为4个_NOP_
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2024-05-02 21:48:56

6

主题

48

回帖

614

积分

高级会员

积分
614
发表于 2024-6-13 11:13:46 | 显示全部楼层
是的,我也是在启动触发后增加延时正常读取了. 谢谢!
终于解决IAP_EEPROM连续写入多个数据读取异常问题 - EEPROM/DataFlash 国芯技术交流网站 - STC全球32位8051爱好者互助交流社区
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=8929
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:25 , Processed in 0.287041 second(s), 83 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表