天宁宁 发表于 2025-6-13 14:27:14

AI8H8K64U移植16S EEPROM读写还是不对

#define      IAP_ADDRESS0x4000   //EEPROM首地址

//烧录时要设定 DATA-FLASH / EEPROM 的大小
//IAP 时 EEPROM的首地址是从 0 开始的

sfr          IAP_TPS   =   0xF5;
// 楼主这是请您设置工作主频,通知等待时间,如果是 24MHz, 就送 0x18
// 楼主这是请您设置工作主频,通知等待时间,如果是 12MHz, 就送 0xC

/*----关闭IAP----------------------------*/
void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                              //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}
/*-从ISP/IAP/EEPROM区域读取一字节-*/
BYTE IapReadByte(WORD 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;
}
/*-写一字节数据到ISP/IAP/EEPROM区域-*/
void IapProgramByte(WORD addr,BYTE 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 IapEraseSector(WORD 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 red_eeprom(void)
            {
                        uint j,k,s,p;
            RunTime_A=IapReadByte(IAP_ADDRESS);   //上料延时
            RunTime_B=IapReadByte(IAP_ADDRESS+1);   //光电延时
            CT=IapReadByte(IAP_ADDRESS+2);          //占空比
                        j=IapReadByte(IAP_ADDRESS+3);//
            k=IapReadByte(IAP_ADDRESS+4);//
            s=IapReadByte(IAP_ADDRESS+5);//
            p=IapReadByte(IAP_ADDRESS+6);//   
            total=j*1000+k*100+s*10+p;   //
                        j=IapReadByte(IAP_ADDRESS+7);//
            k=IapReadByte(IAP_ADDRESS+8);//
            s=IapReadByte(IAP_ADDRESS+9);//
            p=IapReadByte(IAP_ADDRESS+10);//
            FHz=j*1000+k*100+s*10+p;                      //
                        RunTime_C=IapReadByte(IAP_ADDRESS+11);   //
            }
/***************************************/            
            void write_eeprom( )
            {
                        uint j,k,s,p;
            IapEraseSector(IAP_ADDRESS);       //扇区擦除      
            IapProgramByte(IAP_ADDRESS,RunTime_A); //上料延时
            IapProgramByte(IAP_ADDRESS+1,RunTime_B);//光电延时
            IapProgramByte(IAP_ADDRESS+2,CT);               //占空比
                        j=total/1000;
            k=(total-j*1000)/100;
            s=(total-j*1000-k*100)/10;
            p=total-j*1000-k*100-s*10;   
            IapProgramByte(IAP_ADDRESS+3,j);/**/
            IapProgramByte(IAP_ADDRESS+4,k);/**/
            IapProgramByte(IAP_ADDRESS+5,s);/**/
            IapProgramByte(IAP_ADDRESS+6,p);/**/   
            j=FHz/1000;
            k=(FHz-j*1000)/100;
            s=(FHz-j*1000-k*100)/10;
            p=FHz-j*1000-k*100-s*10;   
            IapProgramByte(IAP_ADDRESS+7,j);/**/
            IapProgramByte(IAP_ADDRESS+8,k);/**/
            IapProgramByte(IAP_ADDRESS+9,s);/**/
            IapProgramByte(IAP_ADDRESS+10,p);/**/   
             IapProgramByte(IAP_ADDRESS+11,RunTime_C);//
            }

32位8051 发表于 2025-6-13 15:38:21

楼主不用移植,可以参考我们STC8H8K64U的范例

天宁宁 发表于 2025-6-13 16:31:29

程序太复杂了,我只想读写一个字节 删除
几分钟搞定机器急用 搞了一天了
现在下载到开天斧 打开串口通讯软件COM7没有反应
感谢版主热心帮助

神农鼎 发表于 2025-6-13 16:47:42


烧录时要设定 DATA-FLASH / EEPROM 的大小





神农鼎 发表于 2025-6-13 16:52:30












天宁宁 发表于 2025-6-13 17:23:46




范例程序改了一下 用三个按键写入7F 1F FE
再用一个按键读出后送P2显示
上电后所有P2闪三次
再读出EEPROM显示
结果错误
EEPROM容量已设置0.5K

不复位显示正确
复位后再读数据就错误了
            #include   "reg52.h"
            #include   "intrins.h"
            #define      uchar    unsigned char
            #define      uint   unsigned int
            sfr          IAP_TPS   =   0xF5;
            sbit         KEY_0=P3^2;            //
            sbit         KEY_1=P3^3;            //
            sbit         KEY_2=P3^4;            //
            sbit         KEY_3=P3^5;            //
            uchar      kcounter,kstatus;   //按键计数标志 按键状态标志
/**************Delay*******************************/
            void   Delay_50ms(unsigned int Del_50ms)      //
            {
            unsigned int m;
            for(;Del_50ms>0;Del_50ms--)
            for(m=62450;m>0;m--);
            }
/***********************************/
            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 RstKey()
            {
            kcounter=0;                        //按键计数器归零
            kstatus=0;                         //状态寄存器归零
            }
/*****************按键低电平检测函数*****************/
            void   LowVoltKey(void)            //按键计数器状态标志加一
            {
            kcounter++;                     
            kstatus++;   
            }
/*****************按键高电平检测函数*****************/
            void    HighVoltKey(void)          //按键计数器加一 状态标志归零
            {
            kcounter++;                        //按键计数器加一
            kstatus=0;                         //按键状态标志归零
            }
/***********************************/
            void main()
            {
            P0M0 = 0x00;
            P0M1 = 0x00;
            P1M0 = 0x00;
            P1M1 = 0x00;
            P2M0 = 0x00;
            P2M1 = 0x00;
            P3M0 = 0x00;
            P3M1 = 0x00;
            P4M0 = 0x00;
            P4M1 = 0x00;
            P5M0 = 0x00;
            P5M1 = 0x00;
            Delay_50ms(20);
            P2 =0X00;
            Delay_50ms(20);
            P2 =0XFF;
            Delay_50ms(20);
            P2 =0X00;
                Delay_50ms(20);
            P2 =0XFF;
            Delay_50ms(20);
            P2 =0X00;
            Delay_50ms(20);
            P2 =0XFF;
            P2 = IapRead(0x0400);                     
            Delay_50ms(20);
            while (1)
            {
                  RstKey();
                for(;kcounter<10;)               //按键循环5次
               {
                  if(!KEY_0)                  //按键低电平
                  {
                  LowVoltKey();
                  }
                  else if(~!KEY_0)            //按键高电平
                  {
                  HighVoltKey();
                  }
               }
               if(kstatus>=8)                  /*按键状态标志大于等于3为有效值*/
               {                               /*循环检测 */
                  IapErase(0x0400);
                  IapProgram(0x0400, 0xEF);
               }
//               
                RstKey();
                for(;kcounter<10;)               //按键循环5次
               {
                  if(!KEY_1)                  //按键低电平
                  {
                  LowVoltKey();
                  }
                  else if(~!KEY_1)            //按键高电平
                  {
                  HighVoltKey();
                  }
               }
               if(kstatus>=8)                  /*按键状态标志大于等于3为有效值*/
               {                               /*循环检测 */
               IapErase(0x0400);
               IapProgram(0x0400, 0x7F);
               }
//               
                RstKey();
                for(;kcounter<10;)               //按键循环5次
               {
                  if(!KEY_2)                  //按键低电平
                  {
                  LowVoltKey();
                  }
                  else if(~!KEY_2)            //按键高电平
                  {
                  HighVoltKey();
                  }
               }
               if(kstatus>=8)                  /*按键状态标志大于等于3为有效值*/
               {                               /*循环检测 */
               IapErase(0x0400);
               IapProgram(0x0400, 0xFE);
               }
//                                 
                RstKey();
                for(;kcounter<10;)               //按键循环5次
               {
                  if(!KEY_3)                  //按键低电平
                  {
                  LowVoltKey();
                  }
                  else if(~!KEY_3)            //按键高电平
                  {
                  HighVoltKey();
                  }
               }
               if(kstatus>=8)                  /*按键状态标志大于等于3为有效值*/
               {                               /*循环检测 */
               P2=IapRead(0x0400);                     //P1=0x12
               }
//               
               }
            }





乘风飞扬 发表于 2025-6-13 17:36:57

参考附件例子,这个比较简单

天宁宁 发表于 2025-6-13 18:07:44

            也许正是IAP方式和MOVC方式
            以前一直不了解这两种方式
            范例程序写的4000H 就照抄了
             现在改成0000H
             写入读出复位再读好像可以
            谢谢



            P2 = IapRead(0x0000);                     
            Delay_50ms(20);
            while (1)
            {
                  RstKey();
                for(;kcounter<10;)               //按键循环5次
               {
                  if(!KEY_0)                  //按键低电平
                  {
                  LowVoltKey();
                  }
                  else if(~!KEY_0)            //按键高电平
                  {
                  HighVoltKey();
                  }
               }
               if(kstatus>=8)                  /*按键状态标志大于等于3为有效值*/
               {                               /*循环检测 */
                  IapErase(0x0000);
                  IapProgram(0x0000, 0xEF);
               }
//               
                RstKey();
                for(;kcounter<10;)               //按键循环5次
               {
                  if(!KEY_1)                  //按键低电平
                  {
                  LowVoltKey();
                  }
                  else if(~!KEY_1)            //按键高电平
                  {
                  HighVoltKey();
                  }
               }
               if(kstatus>=8)                  /*按键状态标志大于等于3为有效值*/
               {                               /*循环检测 */
               IapErase(0x0000);
               IapProgram(0x0000, 0x7F);
               }
//               
                RstKey();
                for(;kcounter<10;)               //按键循环5次
               {
                  if(!KEY_2)                  //按键低电平
                  {
                  LowVoltKey();
                  }
                  else if(~!KEY_2)            //按键高电平
                  {
                  HighVoltKey();
                  }
               }
               if(kstatus>=8)                  /*按键状态标志大于等于3为有效值*/
               {                               /*循环检测 */
               IapErase(0x0000);
               IapProgram(0x0000, 0xFE);
               }
//                                 
                RstKey();
                for(;kcounter<10;)               //按键循环5次
               {
                  if(!KEY_3)                  //按键低电平
                  {
                  LowVoltKey();
                  }
                  else if(~!KEY_3)            //按键高电平
                  {
                  HighVoltKey();
                  }
               }
               if(kstatus>=8)                  /*按键状态标志大于等于3为有效值*/
               {                               /*循环检测 */
               P2=IapRead(0x0000);            //P1=0x12
               }
//               
               }
            }
页: [1]
查看完整版本: AI8H8K64U移植16S EEPROM读写还是不对