Ai8H8K64U 连续写入EEPROM出错
在芯片上电后,擦除扇区,写入3个字节没问题,写4个字节就不往下跑了void main()
{
u8 i=0,j=0;
u8 datatp;
u16 tick_cnt = 0;
u8 DGBUG = {0};
IT0 = 1; //使能INT0下降沿中断
EX0 = 1; //使能INT0中断
INTCLKO |= EX2; //使能INT2中断
INTCLKO |= EX3; //使能INT3中断
IO_init();
Timer0_init();
//TR0 = 1;
EA = 0;
Delay1ms(1000);
// GetBaseinfo();
IapEraseSector(0x0200);
IapEraseSector(0x0800);
datatp = IapReadByte(0x0800);
IapProgramByte(0x0800, 0x12);
IapProgramByte(0x0801, 0x13);
IapProgramByte(0x0802, 0x14);
IapProgramByte(0x0803, 0x13); //程序到这里就不跑了,如果注释掉这一句又可以了
datatp = IapReadByte(0x0800);
/*----------------------------
关闭IAP
----------------------------*/
void IapIdle()
{
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0xFF; //将地址设置到非IAP区域
IAP_ADDRL = 0xFF;
}
/*----------------------------
从ISP/IAP/EEPROM区域读取一字节
----------------------------*/
u8 IapReadByte(u16 addr)
{
u8 dat; //数据缓冲区
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 22; //设置等待参数22MHz
IAP_CMD = 1; //设置IAP命令
IAP_ADDRL = addr%256; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
_nop_();
_nop_();
_nop_();
dat = IAP_DATA; //读ISP/IAP/EEPROM数据
IapIdle(); //关闭IAP功能
return dat; //返回
}
/*----------------------------
写一字节数据到ISP/IAP/EEPROM区域
----------------------------*/
void IapProgramByte(u16 addr, u8 dat)
{
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 22; //设置等待参数22MHz
IAP_CMD = 2; //设置IAP命令
IAP_ADDRL = addr%256; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_DATA = dat; //写ISP/IAP/EEPROM数据
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
_nop_();
_nop_();
_nop_();
IapIdle();
}
/*----------------------------
扇区擦除
----------------------------*/
void IapEraseSector(u16 addr)
{
IAP_CONTR = 0x80; //使能IAP
IAP_TPS = 22; //设置等待参数22MHz
IAP_CMD = 3; //设置IAP命令
IAP_ADDRL = addr%256; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
_nop_();
_nop_();
_nop_();
IapIdle();
}
针对用户反馈的STC8H8K64U芯片在连续写入EEPROM时出现异常的问题,以下为专业分析与建议:
首先,从代码逻辑来看,用户在上电后对指定扇区进行了擦除,并尝试连续写入4个字节。然而,在执行第四个写入操作(即IapProgramByte(0x0803, 0x13);)时程序停止运行,表明该操作未能正常完成。
此类问题可能由以下几个方面引起:
1. IAP操作时序问题
STC8H8K64U的IAP功能对时序要求较高。若在连续写入过程中未满足足够的等待时间或未正确释放相关寄存器,可能导致写入失败。建议在每次IAP写入操作后增加适当的延时,以确保芯片内部状态稳定。
2. 扇区保护机制
部分STC系列单片机在IAP操作时会对特定扇区进行保护,防止意外写入。需确认目标地址(如0x0800)是否处于受保护区域。若处于受保护区域,需通过配置寄存器解除保护后再进行写入。
3. IAP函数调用方式
IapEraseSector()和IapProgramByte()等函数通常需要在特定模式下调用,例如关闭全局中断、禁用看门狗等。若未正确设置运行环境,可能导致函数执行异常。建议在调用IAP函数前确保系统处于稳定状态,避免其他中断干扰。
4. 电源稳定性
EEPROM写入过程中,若电源电压波动较大,可能导致写入失败。建议检查电源设计,确保供电稳定,特别是在高负载或快速写入场景下。
5. 代码逻辑冲突
用户代码中存在多个中断使能语句(如EX0 = 1;、INTCLKO |= EX2;等),若中断服务程序未正确处理,可能影响IAP操作的执行流程。建议在IAP操作期间暂时关闭中断,待操作完成后恢复。
综上所述,建议用户按照以下步骤排查问题:
检查IAP操作时序,增加必要的延时;
确认目标地址是否受保护,必要时解除保护;
确保IAP函数调用环境稳定,避免中断干扰;
检查电源设计,确保供电稳定;
在IAP操作期间临时关闭中断,防止逻辑冲突。
若以上措施仍无法解决问题,建议参考STC官方提供的IAP应用手册,或联系技术支持获取进一步帮助。
[本文内容由国芯人工智能辅助生成,仅供参考] IapProgramByte间,加点延时试一下看 程序不完整,缺少IO_init();Timer0_init();GetBaseinfo();函数
是否打开了定时器中断,打开的中断必须要有中断函数
这段程序没发现什么问题
EEPROM相关函数供参考:
void Iap_Idle(void)
{
IAP_CONTR&=~IAPEN;
IAP_CMD=IAP_IDL;
IAP_TRIG=0x00;
IAP_ADDRH=0x80;
IAP_ADDRL=0x00;
}
unsigned char Iap_Read_Byte(unsigned char sector,unsigned int addr)
{
unsigned char dat;
unsigned int add;
add=sector*0x0200+addr;
IAP_CONTR|=IAPEN;
IAP_TPS=IAP_TPS_;
IAP_CMD=IAP_READ;
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
_nop_();
dat=IAP_DATA;
Iap_Idle();
return dat;
}
void Iap_Program_Byte(unsigned char sector,unsigned int addr,unsigned char dat)
{
unsigned int add;
add=sector*0x0200+addr;
IAP_CONTR|=IAPEN;
IAP_TPS=IAP_TPS_;
IAP_CMD=IAP_WRITE;
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_DATA=dat;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
_nop_();
Iap_Idle();
}
void Iap_Erase_Sector(unsigned char sector)
{
unsigned int add;
add=sector*0x0200;
IAP_CONTR|=IAPEN;
IAP_TPS=IAP_TPS_;
IAP_CMD=IAP_ERASE;
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_TRIG=0x5A;
IAP_TRIG=0xA5;
_nop_();
Iap_Idle();
}
页:
[1]