找回密码
 立即注册
查看: 98|回复: 2

AI8H2K12U的EEPROM地址0x0000无法使用问题|已解决

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-09-23 00:23:35
已绑定手机

1

主题

2

回帖

19

积分

新手上路

积分
19
发表于 2025-9-21 23:48:10 | 显示全部楼层 |阅读模式
求助帖~!

AI8H2K12U的EEPROM在ISP中配置为0.5K,使用EEPROM地址0x0001时程序功能正常,0x0000时EEPROM无法保存,测试过修改EEPROM配置从0.5~2K,结果一样;
注释掉的测试代码,在主程序开始前直接在地址0x0000写入5后能够正常读取,地址0x0000的写入和其它地址有什么不一样么?测试除0x0000意外随机的地址也都正常使用




附代码:





#include <AI8H.H>
#include "Delay.h"
#include "STC8H_PWM.h"
#include "INT0and1.h"               
#include "STC8_EEPROM.h"

#define PWM6_E  0x0001  //PWM6档位的EEPROM存储地址(0x0000无法使用原因不明)


u8 Key1;            //档位变量
u8 PWM6_MOD;        //PWM6初始占空比
bit PWM6_KG = 0;    //PWM6开关状态
bit PWM6_UP = 0;    //PWM6更新标识位
bit EEPROM_UP = 0;  //EEPROM更新标识位


void main()
{
    INT0and1_Init();                //外部中断初始化,一定要加在main主程序前
    STC8H_PWM_Init();               //初始化硬件PWM
    P3M0 &= ~0x0c; P3M1 &= ~0x0c;   //P32/33设为准双向口

//    测试   
//    IapEraseSector(IAP_ADDRESS1);   //擦除第1扇区(写入地址所在扇区)
//    IapProgramByte(0x0000,5);          //在地址写入5
//    switch(IapReadByte(0x0000))       //读取EEPROM数据
    switch(IapReadByte(0x0001))     //读取EEPROM数据
    {
        case 2:Key1 = 2;PWM6_MOD = 40;break;
        case 3:Key1 = 3;PWM6_MOD = 50;break;
        case 4:Key1 = 4;PWM6_MOD = 60;break;
        case 5:Key1 = 5;PWM6_MOD = 70;break;
        case 6:Key1 = 6;PWM6_MOD = 80;break;
        case 7:Key1 = 7;PWM6_MOD = 90;break;
        case 8:Key1 = 8;PWM6_MOD = 100;break;
        default:Key1 = 1;PWM6_MOD = 30;break;
    }
        
    while (1)
    {
        if(PWM6_UP)
        {
            PWM6_UP = 0;//清除更新标识位
            
            if(PWM6_KG)//判断开关状态
            {
                PWM_Set(6,PWM6_MOD);
            }else
            {
                PWM_Set(6,0);
            }
        }
        if(EEPROM_UP)
        {
            EEPROM_UP = 0;                  //清除更新标识位
            IapEraseSector(IAP_ADDRESS1);   //擦除第1扇区(写入地址所在扇区)
            IapProgramByte(0x0001,Key1);    //在地址0x00F1写入Key1的值
        }
    }
}


void INT_0(void) interrupt 0                                //外部中断P32接口
{
    Delay(50);//延时消抖
    if(P32 == 0)
    {
        while(P32==0);      //松手检测
        PWM6_KG = ~PWM6_KG; //翻转开关状态
        PWM6_UP = 1;        //开启PWM6更新
    }
}

void INT_1(void) interrupt 2                                //外部中断P33接口
{
    Delay(50);//延时消抖
    if(P33==0)
    {
        while(P33 == 0);//松手检测
        Key1++;
        EEPROM_UP = 1;//开启EEPROM更新
        switch(Key1)//判断档位
        {
            case 2:PWM6_MOD = 40;break;
            case 3:PWM6_MOD = 50;break;
            case 4:PWM6_MOD = 60;break;
            case 5:PWM6_MOD = 70;break;
            case 6:PWM6_MOD = 80;break;
            case 7:PWM6_MOD = 90;break;
            case 8:PWM6_MOD = 100;break;
            default:Key1 = 1;PWM6_MOD = 30;break;
        }
        if(PWM6_KG) //如果PWM6开启,则开启PWM6更新
        {
            PWM6_UP = 1;
        }
    }
}


EEPROM封装函数.c:





#include <AI8H.H>
#include "STC8_EEPROM.h"

/*----------------------------
关闭ISP/IAP/EEPROM功能
使单片机处于安全状态
----------------------------*/
void IapIdle(void)
{
    IAP_CONTR = 0;                  //关闭ISP/IAP/EEPROM功能
    IAP_CMD = 0;                    //待机模式无ISP操作
    IAP_TRIG = 0;                   //ISP/IAP操作时的命令触发寄存器
    IAP_ADDRH = 0x80;               //操作时的地址寄存器高八位
    IAP_ADDRL = 0;                  //操作时的地址寄存器低八位
}

/*----------------------------
从ISP/IAP/EEPROM区域读取一个字节
输入:addr (ISP/IAP/EEPROM地址)
输出:Flash数据
----------------------------*/
u8 IapReadByte(u16 addr)
{
    u8 dat;                        

    IAP_CONTR = 0x80;               //打开IAP功能
    IAP_TPS = ENABLE_IAP;           //设置等待时间,根据系统时钟频率
    IAP_CMD = CMD_READ;             //设为读字节操作
    IAP_ADDRL = addr;               //地址低8位
    IAP_ADDRH = addr >> 8;          //地址高8位
    IAP_TRIG = 0x5a;                //发送触发命令1-必须
    IAP_TRIG = 0xa5;                //发送触发命令2-必须
    _nop_();                        //MCU将保持在这里,直到ISP/IAP/EEPROM操作完成
    dat = IAP_DATA;                 //读取数据
    IapIdle();                      //关闭ISP/IAP/EEPROM功能

    return dat;                     //返回读取的数据
}

/*----------------------------
写一个字节到ISP/IAP/EEPROM区域
addr:ISP/IAP/EEPROM地址
dat :数据
----------------------------*/
void IapProgramByte(u16 addr, u8 dat)
{
    IAP_CONTR = 0x80;               //打开IAP功能
    IAP_TPS = ENABLE_IAP;           //设置等待时间,根据系统时钟频率
    IAP_CMD = CMD_PROGRAM;          //设为写字节操作
    IAP_ADDRL = addr;               //地址低8位
    IAP_ADDRH = addr >> 8;          //地址高8位
    IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
    IAP_TRIG = 0x5a;                //发送触发命令1-必须
    IAP_TRIG = 0xa5;                //发送触发命令2-必须
    _nop_();                        //MCU将保持在这里,直到ISP/IAP/EEPROM操作完成
    IapIdle();                      //关闭ISP/IAP/EEPROM功能
}

/*----------------------------
擦除一个扇区
addr:ISP/IAP/EEPROM地址(起始地址)
----------------------------*/
void IapEraseSector(u16 addr)
{
    IAP_CONTR = 0x80;               //打开IAP功能
    IAP_TPS = ENABLE_IAP;           //设置等待时间,根据系统时钟频率
    IAP_CMD = CMD_ERASE;            //设为扇区擦除操作
    IAP_ADDRL = addr;               //地址低8位
    IAP_ADDRH = addr >> 8;          //地址高8位
    IAP_TRIG = 0x5a;                //发送触发命令1-必须
    IAP_TRIG = 0xa5;                //发送触发命令2-必须
    _nop_();                        //MCU将保持在这里,直到ISP/IAP/EEPROM操作完成
    IapIdle();                      //关闭ISP/IAP/EEPROM功能
}


EEPROM封装函数.h:


#ifndef __STC8_EEPROM_H__
#define __STC8_EEPROM_H__

#include <AI8H.H>
#include "intrins.h"

/*定义操作命令*/
#define CMD_READ    1               //读字节
#define CMD_PROGRAM 2               //写字节
#define CMD_ERASE   3               //扇区擦除


/*根据系统时钟选择等待时间*/
#define ENABLE_IAP 11               //11.0592MHZ    等待时间=系统工作频率/1000000(小数部分四舍五入取整)


//擦除EEPROM的起始地址,以扇区起始地址来擦除,EEPROM大小请在ISP下载工具中进行配置
#define IAP_ADDRESS1 0x0000 //第1扇区  结束地址:0x01FF  注意0x0000无法使用原因不明
#define IAP_ADDRESS2 0x0200 //第2扇区  结束地址:0x03FF
#define IAP_ADDRESS3 0x0400 //第3扇区  结束地址:0x05FF
#define IAP_ADDRESS4 0x0600 //第4扇区  结束地址:0x07FF


//外部可调用的函数声明

u8 IapReadByte(u16 addr);               //读取一个字节
void IapProgramByte(u16 addr, u8 dat);  //写一个字节
void IapEraseSector(u16 addr);          //擦除扇区

#endif



捕获.PNG
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:545
  • 最近打卡:2025-10-01 01:14:42
已绑定手机

17

主题

762

回帖

2150

积分

金牌会员

积分
2150
发表于 2025-9-22 12:21:05 | 显示全部楼层
先用官方例程试试,看看能不能成功
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:3
  • 最近打卡:2025-09-23 00:23:35
已绑定手机

1

主题

2

回帖

19

积分

新手上路

积分
19
发表于 2025-9-23 00:24:26 | 显示全部楼层
小*** 发表于 2025-9-22 12:21
先用官方例程试试,看看能不能成功

还是自己封装函数的问题,使用官方的库函数调用没问题,感谢
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-10-2 02:24 , Processed in 0.112249 second(s), 63 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表