读取STC32G8K64中的EEPROM时,错位了一个字节
最近在做一个项目,使用的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 , 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 =crc >>8;
//UartRxdBuf =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)
{
}
}
先用附件例程烧到芯片进行测试,功能验证正常后再进行修改或者移植。 谢谢了!
把触发子程序换掉,更换编译选项,没再发现出错,
可能是触发后的4个_NOP_有关系
(我的原来只有一个,前面的倒是有加NOP去测,就是没加后面的)。
xmljx 发表于 2024-6-7 15:54
谢谢了!
把触发子程序换掉,更换编译选项,没再发现出错,可能是触发后的4个_NOP_有关系(我的原来只有一 ...
我用STC8H2K08U也出现了这个问题.然后用单独EEPROM代码验证发现写入地址为0,2,4,8...就正常了.但在开ADC/PWM等代码之后还是不行,总是移位一个地址.现在我目前的案子只要写一个u8数据到Flash就暂时没有验证下去了. qq603599910 发表于 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_ 是的,我也是在启动触发后增加延时正常读取了. 谢谢!
终于解决IAP_EEPROM连续写入多个数据读取异常问题 - EEPROM/DataFlash 国芯技术交流网站 - STC全球32位8051爱好者互助交流社区
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=8929
页:
[1]