Sky_chen4 发表于 2025-3-6 10:55:02

地址应该没问题

_奶咖君_ 发表于 2025-3-6 11:12:44

你看到地址前面写的东西了么?

Sky_chen4 发表于 2025-3-6 11:27:29

_奶咖君_ 发表于 2025-3-6 11:12
你看到地址前面写的东西了么?

刚刚试了一下,按照API地址的话,从0x0000开始,程序直接跑不起来了{:4_184:}
按照MOVC的地址,起码还在运行{:4_184:}

angmall 发表于 2025-3-6 11:30:01

Sky_chen4 发表于 2025-3-6 10:55
地址应该没问题

你的程序是用 IAP 方式。
对于 Ai8051U 系列,使用 IAP 方式时,地址数据为 EEPROM 的目标地址,地址从 0000 开始






DebugLab 发表于 2025-3-6 11:59:52

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();
}

Sky_chen4 发表于 2025-3-6 12:34:24

DebugLab 发表于 2025-3-6 11:59
IAP操作,地址从0开始
MOVC读,要加offset
读建议使用MOVC读,速度快


好的,我试试,感谢大佬

Sky_chen4 发表于 2025-3-6 12:35:06

angmall 发表于 2025-3-6 11:30
你的程序是用 IAP 方式。
对于 Ai8051U 系列,使用 IAP 方式时,地址数据为 EEPROM 的目标地址,地址从 0 ...

啊!那我地址用0x0000开始,直接运行不了了

Sky_chen4 发表于 2025-3-6 14:53:16

#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:}

Sky_chen4 发表于 2025-3-6 16:00:16

找到问题,官方的"AI8051U_EEPROM"没有定义"IAP_TPS",
所以直接用会卡死,解决方法也简单。修改这个地方就能正常

运行了。找了半天了,这个是漏了还是故意的?我感觉官方给的库函数不应该出现这种问题
{:4_167:}

页: 1 [2]
查看完整版本: 求助!