写EEPROM遇到的问题
芯片用stc8h2k12u,代码用AIapp-ISP-v6.95W中的范例修改#include "reg51.h"#include "intrins.h"
#define FOSC 11059200UL
#define BRT (65536 - FOSC / 115200 / 4)
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
sfr AUXR = 0x8e;
sfr T2H = 0xd6;
sfr T2L = 0xd7;
sfr IAP_DATA = 0xC2;
sfr IAP_ADDRH = 0xC3;
sfr IAP_ADDRL = 0xC4;
sfr IAP_CMD = 0xC5;
sfr IAP_TRIG = 0xC6;
sfr IAP_CONTR = 0xC7;
sfr IAP_TPS = 0xF5;
void Delay1000ms(void) //@11.0592MHz
{
unsigned char data i, j, k;
i = 57;
j = 27;
k = 112;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void UartInit()
{
SCON = 0x5a;
T2L = BRT;
T2H = BRT >> 8;
AUXR = 0x15;
}
void UartSend(char dat)
{
while (!TI);
TI = 0;
SBUF = dat;
}
void IapIdle()
{
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP区域
IAP_ADDRL = 0;
}
char IapRead(int addr)
{
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数据
IapIdle(); //关闭IAP功能
return dat;
}
void IapProgram(int addr, char dat)
{
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_();
IapIdle(); //关闭IAP功能
}
void IapErase(int addr)
{
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_(); //
IapIdle(); //关闭IAP功能
}
void Delay10ms(void) //@11.0592MHz
{
unsigned char data i, j;
_nop_();
_nop_();
i = 144;
j = 157;
do
{
while (--j);
} while (--i);
}
void main()
{
char i;
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
UartInit();
Delay1000ms();
Delay1000ms();
IapErase(0);
for(i=0;i<64;i++)
UartSend(IapRead(i));
for(i=0;i<64;i++)
{
IapProgram(i, i);
}
for(i=0;i<64;i++)
{
UartSend(IapRead(i));
}
while (1);
}目前遇到的问题是,连续写入时,读出的数据好像被推后一个字节地址,不知道在哪个地方出问题。
工程如下:
楼主这个代码验证无法闭环呀~
[*] IapErase(0);//清空一个扇区
[*] for(i=0;i<64;i++)
[*] UartSend(IapRead(i));//这里必然全是空,0xFF
[*] for(i=0;i<64;i++)
[*] {
[*] IapProgram(i, i);//写入
[*] }
[*]
[*] UartSend(IapRead(i));// i64 ,并且64位置只擦除未写入,0xFF
用附件的例子烧录到芯片里试试,串口助手文本模式打印读写结果 乘风飞扬 发表于 2025-7-7 18:27
用附件的例子烧录到芯片里试试,串口助手文本模式打印读写结果
我试试看 乘风飞扬 发表于 2025-7-7 18:27
用附件的例子烧录到芯片里试试,串口助手文本模式打印读写结果
试了,你第二次读取是写入一个字节就读一个字节的,我把它改成先多个字节写入,再多个字节读取,就出问题了,依然出现字节移位的问题
代码如下:
#include "reg51.h"
#include "intrins.h"
#include "stdio.h"
#define FOSC 11059200UL
#define BRT (65536 - FOSC / 115200 / 4)
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
sfr AUXR = 0x8e;
sfr T2H = 0xd6;
sfr T2L = 0xd7;
sfr IAP_DATA = 0xC2;
sfr IAP_ADDRH = 0xC3;
sfr IAP_ADDRL = 0xC4;
sfr IAP_CMD = 0xC5;
sfr IAP_TRIG = 0xC6;
sfr IAP_CONTR = 0xC7;
sfr IAP_TPS = 0xF5;
void Delay1000ms(void) //@11.0592MHz
{
unsigned char data i, j, k;
i = 57;
j = 27;
k = 112;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void UartInit()
{
SCON = 0x5a;
T2L = BRT;
T2H = BRT >> 8;
AUXR = 0x15;
}
void UartSend(char dat)
{
while (!TI);
TI = 0;
SBUF = dat;
}
void IapIdle()
{
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP区域
IAP_ADDRL = 0;
}
unsigned char IapRead(int addr)
{
char dat;
IAP_CONTR = 0x80; //使能IAP
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数据
IapIdle(); //关闭IAP功能
return dat;
}
void IapProgram(int addr, unsigned char dat)
{
IAP_CONTR = 0x80; //使能IAP
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_();
IapIdle(); //关闭IAP功能
}
void IapErase(int addr)
{
IAP_CONTR = 0x80; //使能IAP
IAP_CMD = 3; //设置IAP擦除命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //
IapIdle(); //关闭IAP功能
}
void Delay10ms(void) //@11.0592MHz
{
unsigned char data i, j;
_nop_();
_nop_();
i = 144;
j = 157;
do
{
while (--j);
} while (--i);
}
void main()
{
char i;
// unsigned char a;
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
UartInit();
IAP_TPS = 11; //设置EEPROM操作等待参数(11.0592MHz),初始化设置一次即可
Delay1000ms();
Delay1000ms();
printf("read1:\r\n");
for(i=0;i<12;i++)
printf("0x%02bx ",IapRead(i));
printf("\r\nread2:\r\n");
IapErase(0);
for(i=0;i<12;i++)
printf("0x%02bx ",IapRead(i));
printf("\r\nread3:\r\n");
for(i=0;i<12;i++)
{
IapProgram(i, i);
printf("0x%02bx ",IapRead(i));
}
Delay10ms();
printf("\r\nread4:\r\n");
for(i=0;i<12;i++)
{
printf("0x%02bx ",IapRead(i));
}
while (1);
}
void UartPutc(unsigned char dat)
{
SBUF = dat;
while(TI == 0);
TI = 0;
}
char putchar(char c)
{
UartPutc(c);
return c;
}
测试结果:
问题暂时解决:就是加长读取中的延时(增加一个或两个_nop_();)
原代码:
unsigned char IapRead(int addr)
{
char dat;
IAP_CONTR = 0x80; //使能IAP
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数据
IapIdle(); //关闭IAP功能
return dat;
}改后代码:
unsigned char IapRead(int addr)
{
char dat;
IAP_CONTR = 0x80; //使能IAP
IAP_CMD = 1; //设置IAP读命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_();_nop_();//增加一个_nop_();
dat = IAP_DATA; //读IAP数据
IapIdle(); //关闭IAP功能
return dat;
}估计是STC8执行代码的速度太快了的缘故吧!
例程为了简化代码,一个循环完成读写操作。
你想测试写完再读,再加一个循环就好了。
IAP_TPS = 11; //设置EEPROM操作等待参数(11.0592MHz),初始化设置一次即可
PrintfInit();
printf("Read1="); //读取EEPROM原先的内容
for(i=0;i<10;i++)
{
a = IapRead(OFFSET+i);
printf("0x%02bx ",a);
if(a == 0xff) a = i;//如果内容为空,则写入初始化数据
else a++; //如果内容非空,在原先基础上加1
}
printf("\r\n");
IapErase(OFFSET); //如果擦写范围跨扇区,需要擦除两个扇区的空间
for(i=0;i<10;i++)
{
IapProgram(OFFSET+i, a);
}
printf("Read2="); //擦除、重写后,读取EEPROM现在的内容
for(i=0;i<10;i++)
{
a = IapRead(OFFSET+i);
printf("0x%02bx ",a);
}
printf("\r\n");
乘风飞扬 发表于 2025-7-8 09:25
例程为了简化代码,一个循环完成读写操作。
你想测试写完再读,再加一个循环就好了。
读取时不加长延时(添加_nop_();)时,字节0出错:
xxkj2010 发表于 2025-7-8 14:49
读取时不加长延时(添加_nop_();)时,字节0出错:
先不要修改例子,直接用例子测试,功能验证正常后再进行修改或者移植。 乘风飞扬 发表于 2025-7-8 15:20
先不要修改例子,直接用例子测试,功能验证正常后再进行修改或者移植。 ...
我是直接下载你发的那个工程的,没有修改,结果出现小问题。我用的芯片是STC8H2K12U-SOP16,如果用STC8H8K64U,就没有问题。
页:
[1]