STC8H2K08U在IAP_EEPROM验证时不能正常写入读取多个数据__已确认修复
本帖最后由 qq603599910 于 2024-6-11 10:30 编辑2024-06-11 最终确认修复结果:之前没有确认准确原因一直在尝试,然后太多不稳定因素干扰导致一直没有找到准确原因,然后前辈回复让我尝试增加延时,我把延时增加在外部步骤代码上没有作用,需要增加在Flash_Read函数代码内部,如图.
char Flash_Read(int addr)
{
char dat;
EA = 0; //禁止中断
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
IAP_CMD = 1; //设置IAP读命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); ====================================== 这里增加2个延时即输出正常.
_nop_(); ======================================
_nop_();
dat = IAP_DATA; //读IAP数据
Flash_Idle(); //关闭IAP功能
EA = 1; //重新允许中断
return dat;
}
=============原文 =======================
各位前辈,最近新拿STC8H2K08U开始做基础代码调试,在IAP_EEPROM验证时不能正常写入读取多个数据,单个地址没有发现异常,基础代码是从范例复制,偶尔烧录一次又能正常读取但没有找到规律.
1: 开始从0x0001开始擦除,然后for循环读取已擦除的5个地址原始值,理论上0x0001-0x0005擦除后应该都是0xffff,但异常是0x0001地址不能被擦除.
2: 从0x0001-0x0005一次写入"0,1,2,3,4"个数值,然后读取已写入值变成"4,0,1,2,3" .我试过N种方法,例如改数据量,用数组,改初始地址,改地址排列都不能找到规律.
3: 调试偶尔烧录后能正常写入读取数据顺序不会变所有地址擦除也正常.但可能第二次烧录后又是读取顺序异常,第一个地址不能被擦除.
以下是验证代码:========================================================
void IAP_Test(void) //EEPROM验证.
{
IAP_Erase(0x0001);//从0x0001起始擦除
for (i=0; i<5; i++)
{
printf("IAP_Erase,%01u:%01u\r\n",(u16)(i),(u16)IAP_Read(0x0001+i));//读取并发送擦除的5个地址(0xFFFF)
}
for (i=0; i<5; i++)
{
IAP_Program(0x0001+i,i); //写入5个地址数据
}
for (i=0; i<5; i++)
{
printf("IAP_Program,%01u:%01u\r\n",(u16)(i),(u16)IAP_Read(0x0001+i));//读取并发送写入5个地址的数据
}
}
以下是打印输出:======================================
时间 数据描述,顺序号:数据
接收:IAP_Erase,0:0 <<<0x0001地址这个应该是65535(0xFFFF)
IAP_Erase,1:65535
IAP_Erase,2:65535
IAP_Erase,3:65535
IAP_Erase,4:65535
IAP_Program,0:4 <<<0x0001地址这个应该是0,被占了一个地址,一次后排.
IAP_Program,1:0
IAP_Program,2:1
IAP_Program,3:2
IAP_Program,4:3
接收:IAP_Erase,0:4 <<< 0x0001地址这次数据"4"上一次写入的值.不能被擦除
IAP_Erase,1:65535
IAP_Erase,2:65535
IAP_Erase,3:65535
IAP_Erase,4:65535
IAP_Program,0:4
IAP_Program,1:0
IAP_Program,2:1
IAP_Program,3:2
IAP_Program,4:3
基础代码是从范例复制==================
#include "inc\eeprom.h"
void IAP_Idle() //IAP关闭
{
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP区域
IAP_ADDRL = 0;
}
char IAP_Read(int addr) //读取IAP
{
char dat;
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
IAP_CMD = 1; //设置IAP读命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
dat = IAP_DATA; //读IAP数据
IAP_Idle(); //关闭IAP功能
return dat;
}
void IAP_Program(int addr, char dat)//写IAP
{
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
IAP_CMD = 2; //设置IAP写命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_DATA = dat; //写IAP数据
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
IAP_Idle(); //关闭IAP功能
}
void IAP_Erase(int addr) //清除IAP地址
{
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 12; //设置等待参数12MHz
IAP_CMD = 3; //设置IAP擦除命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //
IAP_Idle(); //关闭IAP功能
}
加3个nop放慢速度 试一下 用官方例程测试一下,如果结果正确,再进行修改 小飞侠 发表于 2024-4-3 07:50
用官方例程测试一下,如果结果正确,再进行修改
官方例程是单个数据操作没有问题的. 国学芯用 发表于 2024-4-2 17:02
加3个nop放慢速度 试一下
谢谢!尝试了每个操作加延时5ms,还是一样. 1、你的系统时钟,是不是12M?
2、读数据之前关中断,读完后再打开中断 测试一下
国学芯用 发表于 2024-4-3 15:19
测试一下
你好! 今天初步有个结论点:
1: 下载你提供的例程前两次下载是OK的, 后来下载还是EEPROM异常,异常读取值如下(可以确认下载操作是没有疏漏,和USB-CDC代码反复交替验证确认结果):
接收:Key1 pressed.
Read1=0x00 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read2=0x01 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
接收:Key1 pressed.
Read1=0x09 0x01 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
Read2=0x0a 0x02 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
接收:Key1 pressed.
Read1=0x09 0x0a 0x02 0x02 0x03 0x04 0x05 0x06 0x07 0x08
Read2=0x0a 0x0b 0x03 0x03 0x04 0x05 0x06 0x07 0x08 0x09
接收:Key1 pressed.
Read1=0x09 0x0a 0x0b 0x03 0x03 0x04 0x05 0x06 0x07 0x08
Read2=0x0a 0x0b 0x0c 0x04 0x04 0x05 0x06 0x07 0x08 0x09
接收:Key1 pressed.
Read1=0x09 0x0a 0x0b 0x0c 0x04 0x04 0x05 0x06 0x07 0x08
Read2=0x0a 0x0b 0x0c 0x0d 0x05 0x05 0x06 0x07 0x08 0x09
接收:Key1 pressed.
Read1=0x09 0x0a 0x0b 0x0c 0x0d 0x05 0x05 0x06 0x07 0x08
Read2=0x0a 0x0b 0x0c 0x0d 0x0e 0x06 0x06 0x07 0x08 0x09
接收:Key1 pressed.
Read1=0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x06 0x06 0x07 0x08
Read2=0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x07 0x07 0x08 0x09
接收:Key1 pressed.
Read1=0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x07 0x07 0x08
Read2=0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x08 0x08 0x09
接收:Key1 pressed.
Read1=0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x08 0x08
Read2=0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x09 0x09
接收:Key1 pressed.
Read1=0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x09
Read2=0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x0a
接收:Key1 pressed.
Read1=0x0a 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12
Read2=0x0b 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13
接收:Key1 pressed.
Read1=0x13 0x0b 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12
Read2=0x14 0x0c 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13
接收:Key1 pressed.
Read1=0x13 0x14 0x0c 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12
Read2=0x14 0x15 0x0d 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13
2: 使用我自己原来的USB-CDC例程代码发现规律了,就是sys_init()打开ADC功能就EEPROM异常,关闭ADC后EEPROM一直正常读取.
void sys_init()
{
P_SW2 |= 0x80; //扩展寄存器(XFR)访问使能
P_SWX1 = 0x01; //调换P5.4切换为P1.2
////00->准双向 01->推挽PP 10->高阻输入Zin 11->开漏OD
//P0M1 = 0xFF; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x01;
P1M0 = 0x00; //设置为准双向口
//P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00;
P3M0 = 0x00; //设置为准双向口
//P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
//P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
//P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
//P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
//ADC初始化寄存器===配置就EEPROM读取异常,关闭就正常读取EEPROM
//ADCTIM = 0x3f;//设置通道选择时间、保持时间、采样时间
//ADCCFG = RES_FMT + ADC_SPEED;
//ADC模块电源打开后,需等待1ms,MCU内部ADC电源稳定后再进行AD转换
//ADC_CONTR = 0x80 + 0;
}
正常读取信息如下: Read1是原始值,Read2是清空后读取值,Read3是写入后的值.
接收:Read1=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
接收:Read1=0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a
接收:Read1=0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b
接收:Read1=0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c
接收:Read1=0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d
接收:Read1=0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e
接收:Read1=0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
接收:Read1=0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10
接收:Read1=0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11
接收:Read1=0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12
接收:Read1=0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13
接收:Read1=0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13
Read2=0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
Read3=0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14
本帖最后由 qq603599910 于 2024-4-15 11:52 编辑
国学芯用 发表于 2024-4-3 15:19
测试一下
你的例程是在反复验证USB-CDC代码ADC关闭EEPROM读取正常后再烧录回你的原始bin文件都是EEPROM读取异常,但可以确认初始烧录是完全正常读取EEPROM的.现在我的USB-CDC代码关闭ADC后EEPROM读取很稳定,不过我的案子是需要启动ADC的,所以还要麻烦帮忙确认代码,感谢!!!
页:
[1]