你看到地址前面写的东西了么?
刚刚试了一下,按照API地址的话,从0x0000开始,程序直接跑不起来了{:4_184:}
按照MOVC的地址,起码还在运行{:4_184:} Sky_chen4 发表于 2025-3-6 10:55
地址应该没问题
你的程序是用 IAP 方式。
对于 Ai8051U 系列,使用 IAP 方式时,地址数据为 EEPROM 的目标地址,地址从 0000 开始
IAP操作,地址从0开始
MOVC读,要加offset
读建议使用MOVC读,速度快
可以参考我的例程
AI8051U,1K EEPROM
IAP_OFFSET=0xFC00,EEPROM=2sector
sector范围0或1,addr范围0~511
正确设置IAP_OFFSET后,MOVC读函数也自动计算好了,传入的sector从0开始
addr都是从0开始
以下程序供参考:
#include <absacc.h>
#define IAP_TPS_ 24 //等待参数
#define IAP_OFFSET 0xFC00 //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)
{
return *(CBYTE+IAP_OFFSET+sector*0x0200+addr);
}
//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();
}
DebugLab 发表于 2025-3-6 11:59
IAP操作,地址从0开始
MOVC读,要加offset
读建议使用MOVC读,速度快
好的,我试试,感谢大佬 angmall 发表于 2025-3-6 11:30
你的程序是用 IAP 方式。
对于 Ai8051U 系列,使用 IAP 方式时,地址数据为 EEPROM 的目标地址,地址从 0 ...
啊!那我地址用0x0000开始,直接运行不了了 #include "config.h"
#include "Task.h"
#include "system_init.h"
void IapIdle()
{
IAP_CONTR = 0; //禁止IAP操作
IAP_CMD = 0; //去除IAP命令
IAP_TRIG= 0; //防止IAP命令误触发
IAP_ADDRE = 0x00; //将地址设置到非 IAP 区域
IAP_ADDRH = 0x00; //将地址设置到非 IAP 区域
IAP_ADDRL = 0x00;
}
u8 IapRead(u32 EE_address)
{
char dat;
EA = 0;
IAP_CONTR = 0x80; //使能IAP模式
IAP_TPS = 24; //设置IAP TPS为24,即IAP模式下时钟频率为24MHz
IAP_CMD = 1; //读指令
IAP_ADDRE = EE_address >> 16; //送地址高字节(地址需要改变时才需重新送地址)
IAP_ADDRH = EE_address >> 8;//送地址中字节(地址需要改变时才需重新送地址)
IAP_ADDRL = EE_address; //送地址低字节(地址需要改变时才需重新送地址)
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5; //先送5AH,再送A5H到IAP触发寄存器,每次都需要如此
_nop_(); //由于AI8051U是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
_nop_();
_nop_();
_nop_();
dat = IAP_DATA;//读取
IapIdle();
EA = 1;
return dat;
}
void IapProgram(u32 EE_address,u8 dat)
{
EA = 0;
IAP_CONTR = 0x80; //使能IAP模式
IAP_TPS = 24; //设置IAP TPS为24,即IAP模式下时钟频率为24MHz
IAP_CMD = 2; //读指令
IAP_ADDRE = EE_address >> 16; //送地址高字节(地址需要改变时才需重新送地址)
IAP_ADDRH = EE_address >> 8;//送地址中字节(地址需要改变时才需重新送地址)
IAP_ADDRL = EE_address; //送地址低字节(地址需要改变时才需重新送地址)
IAP_DATA = dat;//写入
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5; //先送5AH,再送A5H到IAP触发寄存器,每次都需要如此
_nop_(); //由于AI8051U是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
_nop_();
_nop_();
_nop_();
IapIdle();
EA = 1;
}
void IapErase(u32 EE_address)
{
EA = 0;
IAP_CONTR = 0x80; //使能IAP模式
IAP_TPS = 24; //设置IAP TPS为24,即IAP模式下时钟频率为24MHz
IAP_CMD = 3; //擦除指令
IAP_ADDRE = EE_address >> 16; //送地址高字节(地址需要改变时才需重新送地址)
IAP_ADDRH = EE_address >> 8;//送地址中字节(地址需要改变时才需重新送地址)
IAP_ADDRL = EE_address; //送地址低字节(地址需要改变时才需重新送地址)
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5; //先送5AH,再送A5H到IAP触发寄存器,每次都需要如此
_nop_(); //由于AI8051U是多级流水线的指令系统,触发命令后建议加4个NOP,保证IAP_DATA的数据完成准备
_nop_();
_nop_();
_nop_();
IapIdle();
EA = 1;
}
void main()
{
SYS_Init();
// u8 buf10={1,2,3,4,5,6,7,8,9,2};
// u8 buf1;
// u8 i;
while(1)
{
u8 dat;
IapErase(0x0400);
dat = IapRead(0x0400);
printf("eeprom%d:%d\r\n",0x0400,dat);
IapProgram(0x0400,0x12);
dat = IapRead(0x0400);
printf("eeprom%d:%d\r\n",0x0400,dat);
}
}
按照手册的测试程序成功了,原因暂时不清楚。研究明白继续更贴{:4_167:}
找到问题,官方的"AI8051U_EEPROM"没有定义"IAP_TPS",
所以直接用会卡死,解决方法也简单。修改这个地方就能正常
运行了。找了半天了,这个是漏了还是故意的?我感觉官方给的库函数不应该出现这种问题
{:4_167:}
页:
1
[2]