找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2234|回复: 11
收起左侧

请教stc12C5A60S2单片机内部E2PROM不保存的问题

  [复制链接]
ID:617813 发表于 2021-5-5 11:10 | 显示全部楼层 |阅读模式
100黑币
我使用的是12C5A60S2,郭天祥的单片机开发板,网上找的驱动,num1就是没有保存进EEPROM里去,不知道是哪出的问题,感谢大神们帮帮忙。文件如下:#include <reg52.H>
#include <intrins.h>
#define  uchar unsigned char
#define  uint unsigned int
#define         RdCommand 0x01                //定义ISP的操作命令
#define         prgCommand 0x02
#define         EraseCommand        0x03
#define         Error 1
#define         Ok 0
#define         WaitTime 0x01                //定义CPU的等待时间

sfr  ISP_DATA = 0xE2;
sfr ISP_ADDRH = 0xE3;
sfr ISP_ADDRL = 0xE4 ;

sfr ISP_CMD = 0xE5;
sfr ISP_TRIG = 0xE6;
sfr ISP_CONTR = 0xE7;

sbit duan=P2^6;
sbit wei=P2^7;
sbit key1=P3^4;

uchar code table[]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71 };
uchar num;
void delayms(uint xms)         //毫秒延时
{
  uint i,j;
  for(i=xms;i>0;i--)
                  for(j=110;j>0;j--);
}
void display(uchar shi,uchar ge)  //数码管显示子函数
{
   duan=1;
   P0=table[shi];                 //送位选数据前关闭所有显示,防止打开位选锁存时
   duan=0;
   P0=0xff;
   wei=1;
   P0=0xfe;
   wei=0;
   delayms(5);         

   duan=1;
   P0=table[ge];                 //送位选数据前关闭所有显示,防止打开位选锁存时
   duan=0;
   P0=0xff;
   wei=1;
   P0=0xfd;
   wei=0;
   delayms(5);
}
/*======================打开 ISP,IAP 功能=====================*/
void ISP_IAP_enable(void)
{
         EA=0;                                                           //关中断
         ISP_CONTR=ISP_CONTR & 0x18        ;                //0001,1000
         ISP_CONTR=        ISP_CONTR| 0x01;//WaitTime;         //写入硬件延时
         ISP_CONTR=ISP_CONTR| 0x80;                         //ISPEN=1
}
/*=======================关闭 ISP,IAP==========================*/
void ISP_IAP_disable(void)
{
          ISP_CONTR= ISP_CONTR & 0x7f;       //ISPEN=0
          ISP_TRIG=0x00;
          EA=1;                            //开中断
}
/*=======================公共的触发代码=========================*/
void ISPgoon(void)
{
         ISP_IAP_enable();                   //打开ISP,IAP功能
         ISP_TRIG=0x46;                           //触发ISP_IAP命令字节1
         ISP_TRIG=0xb9;                                //触发ISP_IAP命令字节2
         _nop_();
}
/*=======================字节读=================================*/
unsigned char byte_read(unsigned int byte_addr)
{
        ISP_ADDRH=(unsigned char)(byte_addr >>8);                //地址赋值
        ISP_ADDRL=(unsigned char)(byte_addr &0x00ff);
        ISP_CMD=ISP_CMD &0xf8;                                 //清除低3位
        ISP_CMD=ISP_CMD | RdCommand;                                                         //写读命令
        ISPgoon();                                                                                           //触发执行
        ISP_IAP_disable();                                     //关闭ISP,IAP功能
        return(ISP_DATA);                                                                         //返回读到的数据
}
/*========================扇区擦除================================*/
void SectorErase(unsigned int sector_addr)
{
  unsigned int iSectorAddr;
  iSectorAddr=(sector_addr &0xfe00);                                          //取扇区地址
  ISP_ADDRH=(unsigned char )(iSectorAddr>>8);
  ISP_ADDRL=0x00;
  ISP_CMD=ISP_CMD &0xf8;                                  //清空低3位
  ISP_CMD=ISP_CMD|EraseCommand;                            //擦除命令3
  ISPgoon();                                              //触发执行
  ISP_IAP_disable();                                       //关闭ISP,IAP功能
}
/*=========================字节写====================================*/
void byte_write(unsigned int byte_addr,unsigned char original_data)
{
  ISP_ADDRH=(unsigned char)(byte_addr>>8);                                  //取地址
  ISP_ADDRL=(unsigned char)(byte_addr & 0xff00);
  ISP_CMD =ISP_CMD & 0xf8;                                 //清低3位
  ISP_CMD =ISP_CMD | prgCommand;                                                    //写命令2
  ISP_DATA =original_data;                                 //写入数据准备
  ISPgoon();                                               //触发执行
  ISP_IAP_disable();                                      //关闭IAP功能
}
/*========================main========================================*/
void main()
{
  uchar a,b,num1;
  TMOD=0x01 ;                //设定定时器0为工作方式1
  TH0=(65536-50000)/256;
  TL0=(65536-50000)%256;
  EA=1;
  ET0=1;
  TR0=1;
  num1=byte_read(0x2000);     // 程序开始时读取EEPROM中数据
  if(num1>=60)                                   //防止首次上电时读取出错
                  num1=0;

                while(1)
                {
                  if(num>=20)
        //        if(key1==0)                   //调试用按键
                  {
               num=0;
                   num1++;
                   SectorErase(0x2000);
                   byte_write(0x2000,num1);
                   if(num1==60)
                  {
                           num1=0;  
                   }
                   a=num1/10;
                  b=num1%10;
               
                }
                 display(a,b);

         }

}

void timer0() interrupt 1
{
  TH0=(65536-50000)/256;
  TL0=(65536-50000)%256;
  num++;
}

回复

使用道具 举报

ID:853162 发表于 2021-5-5 14:17 | 显示全部楼层
把unsigned char byte_read(unsigned int byte_addr)的unsigned char改成void
回复

使用道具 举报

ID:617813 发表于 2021-5-5 18:20 | 显示全部楼层
GLP800 发表于 2021-5-5 14:17
把unsigned char byte_read(unsigned int byte_addr)的unsigned char改成void

改成void就提示出错没法执行下去,再帮我看看是哪错了
回复

使用道具 举报

ID:213173 发表于 2021-5-5 20:59 | 显示全部楼层
楼主用的程序适合STC89C52,STC12C5A60S2的ISP寄存器地址和EEPROM地址与STC89C52不一样。
sfr ISP_DATA  = 0xC2;
sfr ISP_ADDRH = 0xC3;
sfr ISP_ADDRL = 0xC4;
sfr ISP_CMD   = 0xC5;
sfr ISP_TRIG  = 0xC6;
sfr ISP_CONTR = 0xC7;
EEPROM地址范围0x0000~0x03ff,第一扇区首地址0x0000,第二扇区首地址0x0200。
回复

使用道具 举报

ID:853162 发表于 2021-5-6 17:24 | 显示全部楼层
lujuguo 发表于 2021-5-5 18:20
改成void就提示出错没法执行下去,再帮我看看是哪错了

看看大佬的回复,STC12C5A60S2的ISP寄存器地址和EEPROM地址与STC89C52不一样,你用的是STC89C52的例程,你把头文件#include <reg52.H>改成#include <STC12C5A.H>,把EEPROM地址都改成0x0200看看行不行,你买的板子应该有STC12C5A60S2的配套资源,我这里只有51的,我改头文件后就会报错,你可以试试看。
回复

使用道具 举报

ID:889094 发表于 2021-5-6 21:31 | 显示全部楼层
4楼地板正解,用前看手册,用什么芯片看什么手册
回复

使用道具 举报

ID:922247 发表于 2021-5-16 20:44 | 显示全部楼层
E2P读写时要确保电源电压稳定。 上电时电压不稳,容易出现意外。在初始化中加1秒的延迟后,再进行E2P操作。如果应用条件允许延迟可以更长些。要确保上电后启动大负载时,电压波动不影响MCU电源。除了读写时电源不稳,没有什么情况会导致E2P异常。如果你这些都注意了,就没问题。 外界干扰问题这完全靠你的经验了,电路设计是否合理,现场假设情况能模拟的话,最好研发时模拟一下,最终达到测试故障率为零在投产,包括模拟一下突然断电,乎断乎通的情况,这个好模拟,不断插拔电源即可,看看能都通过考验。
回复

使用道具 举报

ID:220936 发表于 2021-12-15 10:26 | 显示全部楼层
还有就是stc12c5a60s2擦除需要时间, SectorErase(0x2000);byte_write(0x2000,num1);中间要加delay,我也遇到了这个情况,在坛里找了半天,终于找到原因
回复

使用道具 举报

ID:399179 发表于 2022-5-7 10:56 来自手机 | 显示全部楼层
我也遇到这个问题了,按地板的方法改一下就可以了
回复

使用道具 举报

ID:1026496 发表于 2022-5-15 22:39 | 显示全部楼层
unsigned char byte_read(unsigned int byte_addr) 这个函数返回值应该位int ,  int byte_read(unsigned int byte_addr)
回复

使用道具 举报

ID:963509 发表于 2023-7-29 14:42 | 显示全部楼层
内部的eeprom在使用前删除当前扇区的数据,只能扇区擦除,删除后再按字节写入数据就可以了
回复

使用道具 举报

ID:1010970 发表于 2024-1-1 21:58 | 显示全部楼层
ISP_TRIG=0x46;                           //触发ISP_IAP命令字节1
         ISP_TRIG=0xb9;                                //触发ISP_IAP命令字节2

这两行命令错了 46和b9是89c52的命令字节,手册上5a 和a5才是12单片机的命令字节
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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