找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3345|回复: 34
打印 上一主题 下一主题
收起左侧

STC单片机EEPROM扇区操作问题

[复制链接]
跳转到指定楼层
楼主
各位大佬,关于STC这芯片的EEPROM在进行操作时,如果不按照扇区顺序操作控擦写,能不能有效存入数据?例如:开机初始化时使用第二扇区进行擦写,后面需要设置时使用第一扇区擦写存数据,我经过测试发现第二扇区不能存数据,如下:
void main(void)
{

IO_Init();
Delay(100);

TempSum=IapRead(0x0001);//读第一扇区
TempSum=TempSum<<8|IapRead(0x0002);
ADsodo_flag=IapRead(0x0203);//读第二扇区
camp_dataFlag=ADsodo_flag;
TESample=IapRead(0x0404);//读第三扇区
  TESample=camp_data<<8|IapRead(0x0405);
Delay(500);
Timer0_Init();


  while(1)
{
   
  
  if(AD_cmaxizuFlag_1)
  {
   TESample=tertpe-Set_temp;

   AD_cmaxizuFlag_1=0;
   }
  else
    if(AD_cmaxizuFlag_2)
    {
      TESample=Set_temp-tertpe;
   
      AD_cmaxizuFlag_2=0;
    }
   
  if(EepromFlag_1==2)
  {
    IapErase(0x0000);//擦除第一扇区
    IapProgram(0x0001,TempSum>>8);//写入第一扇区
   IapProgram(0x0002,TempSum);
   EepromFlag_1=0;
     }
  
  if(EepromFlag_2==2)
  {

    IapErase(0x0200);//擦除第二扇区
    IapProgram(0x0203,ADsodo_flag);//写入第二扇区
    IapErase(0x0400);//擦除第三扇区
    IapProgram(0x0404,TESample>>8);//写入第三扇区
   IapProgram(0x0405,TESample);
    EepromFlag_2=0;
   }
if(Eepromflag_A)//开机按键初始化第一次写入
{
  IapErase(0x0200);//擦除第二扇区
    IapProgram(0x0203,ADsodo_flag);//写入第二扇区
Eepromflag_A=0;
}
}
}

  }
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:322939 发表于 2021-12-14 15:50 | 只看该作者
还有就是第一扇区可以保存读出,但第二和第三扇区却不能保存
回复

使用道具 举报

板凳
ID:624769 发表于 2021-12-14 16:43 | 只看该作者
任何扇区 都能擦,写, 读。

但是,前提是,这些扇区真实存在, 如果你的Eeprom 只有 512字节 是只有 一个扇区的。

不清楚你的芯片型号,不清楚你的设置,看不到你擦,写,读 操作的代码, 也看不到Eeprom 初始化代码, 说什么都是猜。
回复

使用道具 举报

地板
ID:213173 发表于 2021-12-14 16:57 | 只看该作者
不必按照扇区顺序操作,可以选择在有效扇区范围内任意扇区的任意地址读写。一般从0开始读写,不易人为出错。每个扇区512字节。
回复

使用道具 举报

5#
ID:322939 发表于 2021-12-14 17:59 | 只看该作者
wulin 发表于 2021-12-14 16:57
不必按照扇区顺序操作,可以选择在有效扇区范围内任意扇区的任意地址读写。一般从0开始读写,不易人为出错 ...

但实际上却不能存入数据,没作用,只有第一扇区有作用,不知道那里出错了
回复

使用道具 举报

6#
ID:213173 发表于 2021-12-14 20:25 | 只看该作者
LAW1100 发表于 2021-12-14 17:59
但实际上却不能存入数据,没作用,只有第一扇区有作用,不知道那里出错了

代码不全,神仙也不知道那里出错了。
回复

使用道具 举报

7#
ID:322939 发表于 2021-12-15 08:06 | 只看该作者
wulin 发表于 2021-12-14 20:25
代码不全,神仙也不知道那里出错了。

代码是模块化的,太多了,上传这里你们看了要花大量时间理解,用的芯片是STC8H1K08这款的
回复

使用道具 举报

8#
ID:322939 发表于 2021-12-15 09:44 | 只看该作者
如果将数据全部放在第一扇区,也是只有第一个数据能读出来,其它数据很大(FFH)不是原来数据,存不了
回复

使用道具 举报

9#
ID:322939 发表于 2021-12-15 09:49 | 只看该作者
void main(void)
{

        IO_Init();
        Delay(1000);
       
        TempSum=IapRead(0x0001);//读出第一扇区1和2地址数据
        TempSum=TempSum<<8|IapRead(0x0002);
        ADsodo_flag=IapRead(0x0003);//第3地址数据
        camp_dataFlag=ADsodo_flag;
        TESample=IapRead(0x0004);//第4和5地址数据
        TESample=camp_data<<8|IapRead(0x0005);
        Delay(500);

        Timer0_Init();
while(1)
        {
if(EepromFlag_1==2)
         {
                  IapErase(0x0000);//擦除第一扇区
                  IapProgram(0x0001,TempSum>>8);//写入数据
                        IapProgram(0x0002,TempSum);
                        IapProgram(0x0003,ADsodo_flag);//写入
                         IapProgram(0x0004,TESample>>8);//写入
                        IapProgram(0x0005,TESample);
                        EepromFlag_1=0;
                   }
           if(EepromFlag_2==2)
         {
              IapErase(0x0000);//擦除第一扇区
                  IapProgram(0x0001,TempSum>>8);//写入数据
                        IapProgram(0x0002,TempSum);
                        IapProgram(0x0003,ADsodo_flag);//写入
                         IapProgram(0x0004,TESample>>8);//写入
                        IapProgram(0x0005,TESample);
                       EepromFlag_2=0;
                   }
}

回复

使用道具 举报

10#
ID:213173 发表于 2021-12-15 11:40 | 只看该作者
LAW1100 发表于 2021-12-15 08:06
代码是模块化的,太多了,上传这里你们看了要花大量时间理解,用的芯片是STC8H1K08这款的

不能正常读写eeprom的常见原因是受中断干扰或VCC电压不稳且过低。
回复

使用道具 举报

11#
ID:322939 发表于 2021-12-15 13:49 | 只看该作者
wulin 发表于 2021-12-15 11:40
不能正常读写eeprom的常见原因是受中断干扰或VCC电压不稳且过低。

为何第一扇区的第1和2地址能正常读写,其它数据却不能正常读写呢?何况在进行EPROM操作时试过将中断关闭写入后再开中断也不行,供电电压是3.3V,
回复

使用道具 举报

12#
ID:624769 发表于 2021-12-15 14:11 | 只看该作者
LAW1100 发表于 2021-12-15 08:06
代码是模块化的,太多了,上传这里你们看了要花大量时间理解,用的芯片是STC8H1K08这款的

所以说, 一直强调,要先说芯片型号, 就是没人听。

进入 Main 以后  一定要写一句:

IAP_TPS = 24;     // 这里具体数值 取决于你的晶振速度 多少  MHz  四舍五入原则  24MHz  就写24,22.1184MHz 就写 22
回复

使用道具 举报

13#
ID:322939 发表于 2021-12-15 14:31 | 只看该作者
188610329 发表于 2021-12-15 14:11
所以说, 一直强调,要先说芯片型号, 就是没人听。

进入 Main 以后  一定要写一句:

这位大佬,这一句为什么要特别加在Main里呢,例程和手册也没说明。我在另一模块设置里也有这句.
/***********初始化*************/
void IapIdle()
{
    IAP_CONTR =0;                           
    IAP_CMD =0;                                
    IAP_TRIG =0;                              
    IAP_ADDRH =0x80;                           
    IAP_ADDRL =0;
}
/************读数据************/
u8 IapRead(u16 addr_c)
{
     char dat;
     u8 q;
    IAP_CONTR=0x80;                        
    IAP_TPS=24;                  //频率设置24MHZ
    IAP_CMD=1;                                
    IAP_ADDRL=addr_c;                           
    IAP_ADDRH=addr_c>>8;                     
    IAP_TRIG=0x5a;                           
    IAP_TRIG=0xa5;                           
    for(q=0;q<3;q++);
    dat=IAP_DATA;                             
    IapIdle();                                 

    return dat;
}
/*************写数据***********/
void IapProgram(u16 addr, u16 dat)
{
     u8 v;
    IAP_CONTR=0x80;                        
    IAP_TPS=24;                                //24MHZ
    IAP_CMD=2;                                
    IAP_ADDRL=addr;                           
    IAP_ADDRH=addr>>8;                     
    IAP_DATA=dat;                           
    IAP_TRIG=0x5a;                           
    IAP_TRIG=0xa5;                           
   for(v=0;v<3;v++);
    IapIdle();                                 
   
}
/***************擦除************/
void IapErase(u16 addr_a)
{
    u8 u;
    IAP_CONTR=0x80;                        
          IAP_TPS=24;                                //24MHz
    IAP_CMD=3;                                
    IAP_ADDRL=addr_a;                        
    IAP_ADDRH=addr_a>>8;                  
    IAP_TRIG=0x5a;                           
    IAP_TRIG=0xa5;                           
    for(u=0;u<3;u++);                                    
    IapIdle();                                
  
}
回复

使用道具 举报

14#
ID:322939 发表于 2021-12-15 15:27 | 只看该作者
IAP_TPS=24;这句我加在main的开头或者后面(while里)也是不行,只有第一扇区的数据能读写,其它读写不了
回复

使用道具 举报

15#
ID:226055 发表于 2021-12-15 16:53 | 只看该作者
   STC8H系列的在对片内E2PROM操作时(片内FLASH亦然),多了个IAP_TPS寄存器,这是对以前单片机(比如STC15系列)的优化。这样对E2PROM的操作所需时间硬件自动控制,用户只需根系统工作频率配置
IAP_TPS寄存器即可。手头有艾克姆科技STC8H3K64S4开发板的源码,已测试,好用。附件附上。

    1、上个图片,实验是通过串口调试助手来操作片内FLASH的。



    2、片内FLASH操作是需要下载时分配一下E2PROM空间的,如果单片机本身有E2PROM则无需分配。

    3、在对分配了的E2PROM操作时,地址空间不需要加偏移量,即依然从0x0000来操作。这和之前对STC15系列片内FLASH操作不一样,请知悉。

    4、源码见附件,同为STC8H,寄存器基本一致,具有很高的参考价值。













实验2-16-1:片内FLASH读写 - 单个字节(STC8H3K64S4).rar

1.16 MB, 下载次数: 27

回复

使用道具 举报

16#
ID:213173 发表于 2021-12-15 17:40 | 只看该作者
LAW1100 发表于 2021-12-15 14:31
这位大佬,这一句为什么要特别加在Main里呢,例程和手册也没说明。我在另一模块设置里也有这句.
/****** ...

void IapProgram(u16 addr, u16 dat)   这样写形参 u16 dat 的依据是什么?
回复

使用道具 举报

17#
ID:322939 发表于 2021-12-15 17:44 | 只看该作者
wulin 发表于 2021-12-15 17:40
void IapProgram(u16 addr, u16 dat)   这样写形参 u16 dat 的依据是什么?

u16这是在另一模块宏定义无符号变量的缩略
回复

使用道具 举报

18#
ID:624769 发表于 2021-12-15 18:47 | 只看该作者
先说 你 main() 函数里的问题
TempSum=IapRead(0x0001);//读第一扇区
TempSum=TempSum<<8|IapRead(0x0002);


上面这两句代码,我能理解, 把 0x0001 0x0002 的内容读出来,然后,合并。

TESample=IapRead(0x0404);//读第三扇区
  TESample=camp_data<<8|IapRead(0x0405);

但是,这两句代码,我无法理解,你能解释一下么??? 包括哪个 camp_data 是从哪里来的?


然后,你的写Eeprom 子函数 的 u16 dat  也是有问题的。 不过等上面的问题你解答后,我们再讨论后续问题。
回复

使用道具 举报

19#
ID:213173 发表于 2021-12-15 20:07 | 只看该作者
LAW1100 发表于 2021-12-15 17:44
u16这是在另一模块宏定义无符号变量的缩略

就从你的答复看,你根本没有理解我为什么这么问。难道你把无符号字符型数据宏定义为u16?由此推断你的程序中类似问题不会少。出现异常就不足为奇了。
回复

使用道具 举报

20#
ID:57657 发表于 2021-12-15 21:49 | 只看该作者
LAW1100 发表于 2021-12-15 09:44
如果将数据全部放在第一扇区,也是只有第一个数据能读出来,其它数据很大(FFH)不是原来数据,存不了

你定义的都是全局变量,也不知道是什么中断修改了变量的值。

单片机内置EEPROM 不是真正的EEPROM,而是Flash闪存。
只有字节读、字节写、扇区擦除,没有字节擦除,二进制1写0不可逆,只有擦除才可以全部恢复为1,一擦一扇区(512字节)。
回复

使用道具 举报

21#
ID:47286 发表于 2021-12-16 00:07 | 只看该作者
wulin 发表于 2021-12-15 20:07
就从你的答复看,你根本没有理解我为什么这么问。难道你把无符号字符型数据宏定义为u16?由此推断你的程 ...

18 19楼两位大佬 跟风讨论一下这句 void IapProgram(u16 addr, u16 dat)

第一个用u16没问题 是地址 16位的 第二个是要写入的数据 应该是8位的 但我觉得写u16也没事吧 只有8位 就是说即便16位也只取低8位 高8位自动就扔了 如果赋值是16位的 那结果也是低8位 先不说结果对不对 应该能正常执行吧
回复

使用道具 举报

22#
ID:322939 发表于 2021-12-16 08:12 | 只看该作者
188610329 发表于 2021-12-15 18:47
先说 你 main() 函数里的问题
TempSum=IapRead(0x0001);//读第一扇区
TempSum=TempSum

(TESample)这个是AD值与设定值相加减后的数值,存入第三扇区第4和5的地址(因为是16位,所以拆分8位存入,然后读出来合并的)。在形参里无符号变量不能这样使用(u16 ...)???
回复

使用道具 举报

23#
ID:322939 发表于 2021-12-16 08:14 | 只看该作者
wulin 发表于 2021-12-15 20:07
就从你的答复看,你根本没有理解我为什么这么问。难道你把无符号字符型数据宏定义为u16?由此推断你的程 ...

#define  u16  unsigned int  这样定义没问题呀
回复

使用道具 举报

24#
ID:322939 发表于 2021-12-16 08:20 | 只看该作者
dzbj 发表于 2021-12-16 00:07
18 19楼两位大佬 跟风讨论一下这句 void IapProgram(u16 addr, u16 dat)

第一个用u16没问题 是地址 1 ...

第二扇区存入的是8位数据,它的数值很小(要么是0,要么是1或2)用来区分读取那个区块功能,如:if(0==camp_dataFlag)
{
........
}
if(1===camp_dataFlag)
{
  ...........
}
回复

使用道具 举报

25#
ID:322939 发表于 2021-12-16 08:21 | 只看该作者
dzbj 发表于 2021-12-16 00:07
18 19楼两位大佬 跟风讨论一下这句 void IapProgram(u16 addr, u16 dat)

第一个用u16没问题 是地址 1 ...

现在读出来是255的数据,根本存不了。
回复

使用道具 举报

26#
ID:213173 发表于 2021-12-16 08:38 | 只看该作者
dzbj 发表于 2021-12-16 00:07
18 19楼两位大佬 跟风讨论一下这句 void IapProgram(u16 addr, u16 dat)

第一个用u16没问题 是地址 1 ...

不是说这样写一定会出错,而是说写代码要严谨,要养成好习惯。从这点推断楼主的程序中类似问题可能还有。曾经有人把无符号整型数据宏定义u8,无符号字符型数据宏定义u16。特别是使用他人不规范的模块,结果出错乱找,一会怀疑芯片,一会怀疑Keil,搞得焦头烂额。
回复

使用道具 举报

27#
ID:47286 发表于 2021-12-16 10:47 | 只看该作者
wulin 发表于 2021-12-16 08:38
不是说这样写一定会出错,而是说写代码要严谨,要养成好习惯。从这点推断楼主的程序中类似问题可能还有。 ...

大佬说的是 好习惯很重要 可用避免很多麻烦
回复

使用道具 举报

28#
ID:47286 发表于 2021-12-16 10:58 | 只看该作者
LAW1100 发表于 2021-12-16 08:20
第二扇区存入的是8位数据,它的数值很小(要么是0,要么是1或2)用来区分读取那个区块功能,如:if(0==ca ...

你的问题我帮不上 因为我自己水平就不怎么样 仅建议 你试试不写其它程序 只写扇区读写函数 而且只写0 1 2扇区第0位 如果能写进去 那就是你程序的事 再找毛病吧 不做最基本的测试 只问为什么别人也确实不知道怎么弄 毕竟程序是你写的 别人不知道啊

STC的片子各系列我基本都用过 虽然操作上略有不同 但没出现你说的问题 我自己用的扇区操作函数也是封装的模块 写不同程序或者不同片子只是调用 也没出过什么问题 就像听说有人喝白开水得脚气 貌似根本不可能的事 自己先就蒙b 还咋帮别人
回复

使用道具 举报

29#
ID:322939 发表于 2021-12-17 08:56 | 只看该作者
已经找到问题原因了,多谢各位热心解答。
回复

使用道具 举报

30#
ID:161164 发表于 2021-12-17 10:54 | 只看该作者
LAW1100 发表于 2021-12-17 08:56
已经找到问题原因了,多谢各位热心解答。

不说一下问题原因吗?
让后人遇到相同问题有一个解决的方向
回复

使用道具 举报

31#
ID:879348 发表于 2021-12-17 11:13 | 只看该作者
lkc8210 发表于 2021-12-17 10:54
不说一下问题原因吗?
让后人遇到相同问题有一个解决的方向

那肯定是代码问题
回复

使用道具 举报

32#
ID:322939 发表于 2021-12-17 17:57 | 只看该作者
读出来的数据被中断打乱了,因为刚开机时显示正常,但过了1秒后显示跳变,正在查找是那里造成的。
回复

使用道具 举报

33#
ID:624769 发表于 2021-12-17 19:44 | 只看该作者
LAW1100 发表于 2021-12-16 08:12
(TESample)这个是AD值与设定值相加减后的数值,存入第三扇区第4和5的地址(因为是16位,所以拆分8位存 ...

仔细看 在18楼问你的问题,

TESample=IapRead(0x0404);//读第三扇区
  TESample=camp_data<<8|IapRead(0x0405);

红字部分 到底什么 鬼??
回复

使用道具 举报

34#
ID:960619 发表于 2021-12-17 22:30 来自手机 | 只看该作者
Stc8h1k08用官方例程,今天刚用过
回复

使用道具 举报

35#
ID:322939 发表于 2021-12-18 08:50 | 只看该作者
188610329 发表于 2021-12-17 19:44
仔细看 在18楼问你的问题,

TESample=IapRead(0x0404);//读第三扇区

我在这里输入代码时输错了,忘了改过来。抱歉
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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