STC8H3K64S2 EEPROM 操作
主控型号: STC8H3K64S2用户EEPROM大小为1K(下载程序时配置)
//sfr IAP_CMD = 0xC5;
#define IAP_STANDBY() IAP_CMD = 0 //IAP空闲命令(禁止)
#define IAP_READ() IAP_CMD = 1 //IAP读出命令
#define IAP_WRITE() IAP_CMD = 2 //IAP写入命令
#define IAP_ERASE() IAP_CMD = 3 //IAP擦除命令
//sfr IAP_TRIG= 0xC6;
#define IAP_TRIG()do{ IAP_TRIG = 0x5A, IAP_TRIG = 0xA5 } while(0) // IAP触发命令
// 7 6 5 4 3 21 0 Reset Value
//sfr IAP_CONTR = 0xC7; IAPEN SWBS SWRST CFAIL- -- - 0000,x000 //IAP Control Register
#define IAP_EN (1<<7)
#define IAP_SWBS (1<<6)
#define IAP_SWRST (1<<5)
#define IAP_CMD_FAIL (1<<4)
#define IAP_ENABLE() do{ IAP_CONTR = IAP_EN; IAP_TPS = MAIN_Fosc / 1000000; } while(0)
#define IAP_DISABLE() do{ IAP_CONTR = 0; IAP_CMD = 0; IAP_TRIG = 0; IAP_ADDRH = 0xff; IAP_ADDRL = 0xff; } while(0)
void F_EEPROM_Test(void)
{
u16 EE_address = 0xFC00;
u8 WrDataBuf = {0x55,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
u8 RdDataBuf = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
u16 number;
EA = 0; //禁止中断
// 先擦除
IAP_ENABLE(); //设置等待时间,允许IAP操作,送一次就够
IAP_ERASE(); //宏调用, 送扇区擦除命令,命令不需改变时,不需重新送命令
//只有扇区擦除,没有字节擦除,512字节/扇区。
//扇区中任意一个字节地址都是扇区地址。
IAP_ADDRH = (EE_address) / 256; //送扇区地址高字节(地址需要改变时才需重新送地址)
IAP_ADDRL = (EE_address) % 256; //送扇区地址低字节
//触发EEPROM操作
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
// 写
IAP_ENABLE(); //设置等待时间,允许IAP操作,送一次就够
IAP_WRITE(); //宏调用, 送扇区擦除命令,命令不需改变时,不需重新送命令
for (number = 0; number < 9; ++number)
{
//只有扇区擦除,没有字节擦除,512字节/扇区。
//扇区中任意一个字节地址都是扇区地址。
IAP_ADDRH = (EE_address) / 256; //送扇区地址高字节(地址需要改变时才需重新送地址)
IAP_ADDRL = (EE_address) % 256; //送扇区地址低字节
IAP_DATA = WrDataBuf;
//触发EEPROM操作
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
EE_address++;
}
EE_address = 0xFC00;
IAP_ENABLE(); //设置等待时间,允许IAP操作,送一次就够
IAP_READ(); //送字节读命令,命令不需改变时,不需重新送命令
for (number = 0; number < 9; ++number)
{
IAP_ADDRH = EE_address / 256; //设置 IAP 地址高字节
IAP_ADDRL = EE_address % 256; //设置 IAP 地址低字节
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();
_nop_();
RdDataBuf = IAP_DATA; //读 IAP 数据
EE_address++;
}
// 判断写入与读出数据是否相同
for (number = 0; number < 9; ++number)
{
if(RdDataBuf != WrDataBuf)
{
break;
}
}
if(number < 9)
{
P55 = 0;
_nop_(); // 不同 仿真运行时跳到此处
}
else
{
P55 = 1;
_nop_(); // 相同
}
EA = 1; //使能中断
}
能不能帮看看是哪的问题?谢谢.
另外问一下,写FLASH完成后,能不能有Memory里观察到数据的变化?
还在STC-ISP里的EEPROM文件这设置的EEPROM数据,通过下载到MCU后,在Memory只能看到代码部分是有数据(非0xff),
但EEPROM数据看不到,还是这颗IC,EEPROM空间为1K,那EEPROM数据应该是从0xFC00开始存放吧? 本帖最后由 乘风飞扬 于 2023-3-4 17:52 编辑
STC8系列的EEPROM操作的地址是相对地址,不是Flash的绝对地址。
烧录时EEPROM大小设置1K的话,EEPROM的地址范围就是0000H~03FFH之间,不能使用0xFC00作为EEPROM操作地址。
可将EEPROM内容读取到全局变量里面观察,或者通过串口打印出来查看。
另外需要注意,烧录(包括仿真点击DEBUG按钮)时,在将程序烧写到芯片前会先擦除Flash,EEPROM里面的数据也会被擦除。
乘风飞扬 发表于 2023-3-4 17:43
STC8系列的EEPROM操作的地址是相对地址,不是Flash的绝对地址。
烧录时EEPROM大小设置1K的话,EEPROM的地址 ...
例如:STC8H1K28 这个型号的 FLASH为 28K,此时若用户想分出其中的 8K 作为 EEPROM 使用则EEPROM 的物理地址则为28K 的最后 8K,物理地址为 5000h~6FFFh,
当然,用户若使用IAP 的方式进行访问,目标地址仍然从 0000h 开始,到 1FFFh 结束,
当使用 MOVC 读取则需要从 5000h 开始,到6FFFh 结束。
注意: STC8HIK28 这个型号的程序空间为 28K,即整个 28K 的范围均可运行程序,即使在ISP 下载时将 28K 最后的 8K 设置为 EEPROM 使用,
但这分配的 8K 空间仍然可以运行程序。其它可自定义 EEPROM 大小的型号与此类似。
感谢,还是看资料不够仔细.
防止其它人犯同样的错误,再将这个说明加上来.
其实这个备注可以再加到范例部分去.
即,MCU设置EEPROM区间为从后开始算.但IAP方式仿真却是从00开始.MOVC才是从实际FLASH地址开始.
页:
[1]