找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STC15W单片机EEPROM怎么读写?

  [复制链接]
跳转到指定楼层
楼主
ID:608872 发表于 2021-5-20 18:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
学单片机时间不长,现在需要用到掉电保存参数的功能,看了官方手册测试程序,有很多不懂的地方。比如怎么一次写入5个变量,然后在一次性读出来。还有扇区的高位和低位地址怎么写

单片机源程序如下:
  1.     /*----------------------------
  2.     关闭IAP功能
  3.     ----------------------------*/
  4.     void IapIdle()
  5.     {
  6.     IAP_CONTR = 0; //关闭IAP功能
  7.     IAP_CMD = 0; //清除命令寄存器
  8.     IAP_TRIG = 0; //清除触发寄存器
  9.     IAP_ADDRH = 0x80; //将地址设置到非IAP区域
  10.     IAP_ADDRL = 0;
  11.     }
  12.     /*----------------------------
  13.     从ISP/IAP/EEPROM区域读取一字节
  14.     ----------------------------*/
  15.     char IapRead(int addr)
  16.     {
  17.     char dat;
  18.     IAP_CONTR = WT_12M; //使能IAP
  19.     IAP_CMD = 1; //设置IAP读命令
  20.     IAP_ADDRL = addr; //设置IAP低地址
  21.     IAP_ADDRH = addr >> 8; //设置IAP高地址
  22.     IAP_TRIG = 0x5a; //写触发命令(0x5a)
  23.     IAP_TRIG = 0xa5; //写触发命令(0xa5)
  24.     _nop_();
  25.     dat = IAP_DATA; //读IAP数据
  26.     IapIdle(); //关闭IAP功能
  27.     return dat;
  28.     }
  29.     /*-------------------------------
  30.     写一字节数据到ISP/IAP/EEPROM区域
  31.     -------------------------------*/
  32.     void IapProgram(int addr, char dat)
  33.     {
  34.     IAP_CONTR = WT_12M; //使能IAP
  35.     IAP_CMD = 2; //设置IAP写命令
  36.     IAP_ADDRL = addr; //设置IAP低地址
  37.     IAP_ADDRH = addr >> 8; //设置IAP高地址
  38.     IAP_DATA = dat; //写IAP数据
  39.     IAP_TRIG = 0x5a; //写触发命令(0x5a)
  40.     IAP_TRIG = 0xa5; //写触发命令(0xa5)
  41.     _nop_();
  42.     IapIdle(); //关闭IAP功能
  43.     }
  44.     /*----------------------------
  45.     ISP/IAP/EEPROM扇区擦除
  46.     ----------------------------*/
  47.     void IapErase(int addr)
  48.     {
  49.     IAP_CONTR = WT_12M; //使能IAP
  50.     IAP_CMD = 3; //设置IAP擦除命令
  51.     IAP_ADDRL = addr; //设置IAP低地址
  52.     IAP_ADDRH = addr >> 8; //设置IAP高地址
  53.     IAP_TRIG = 0x5a; //写触发命令(0x5a)
  54.     IAP_TRIG = 0xa5; //写触发命令(0xa5)
  55.     _nop_(); //
  56.     IapIdle(); //关闭IAP功能
  57.     }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2021-5-20 20:59 | 只看该作者
给你写一个一看就能明白的示例
  1. #include <STC15F2K60S2.H>    //通用头文件
  2. #include <intrins.h>                                //库头文件
  3. #define uint unsigned int                         //宏定义数据类型uint
  4. #define uchar unsigned char                 //宏定义数据类型uchar
  5. //宏定义ISP的操作命令
  6. #define CMD_IDLE    0               //空闲模式
  7. #define CMD_READ    1               //IAP字节读命令
  8. #define CMD_PROGRAM 2               //IAP字节编程命令
  9. #define CMD_ERASE   3               //IAP扇区擦除命令
  10. #define ENABLE_IAP  0x82            //CPU的等待时间
  11. #define IAP_ADDRESS 0x0000                        //测试地址

  12. /*----------------------------
  13.         关闭IAP功能
  14. ----------------------------*/
  15. void IapIdle()
  16. {
  17.     IAP_CONTR = 0;                  //关闭IAP功能
  18.     IAP_CMD = 0;                    //清除命令寄存器
  19.     IAP_TRIG = 0;                   //清除触发寄存器
  20.     IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
  21.     IAP_ADDRL = 0;
  22. }
  23. /*----------------------------
  24. 从ISP/IAP/EEPROM区域读取一字节
  25. ----------------------------*/
  26. uchar IapReadByte(uint addr)
  27. {
  28.     uchar dat;                       //数据缓冲区
  29.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  30.     IAP_CMD = CMD_READ;             //设置IAP命令
  31.     IAP_ADDRL = addr;               //设置IAP低地址
  32.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  33.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  34.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  35.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  36.     dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
  37.     IapIdle();                      //关闭IAP功能
  38.     return dat;                     //返回
  39. }
  40. /*-------------------------------
  41. 写一字节数据到ISP/IAP/EEPROM区域
  42. --------------------------------*/
  43. void IapProgramByte(uint addr, uchar dat)
  44. {
  45.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  46.     IAP_CMD = CMD_PROGRAM;          //设置IAP命令
  47.     IAP_ADDRL = addr;               //设置IAP低地址
  48.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  49.     IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
  50.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  51.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  52.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  53.     IapIdle();                      //关闭IAP功能
  54. }
  55. /*----------------------------
  56. ISP/IAP/EEPROM扇区擦除
  57. ----------------------------*/
  58. void IapEraseSector(uint addr)
  59. {
  60.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  61.     IAP_CMD = CMD_ERASE;            //设置IAP命令
  62.     IAP_ADDRL = addr;               //设置IAP低地址
  63.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  64.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  65.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  66.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  67.     IapIdle();                      //关闭IAP功能
  68. }

  69. /**ms延时子程序(11.0592MHz 1T)****/
  70. void delayms(uint k)
  71. {
  72.         uint i,j;
  73.         for(i=k;i>0;i--)
  74.                 for(j=829;j>0;j--);
  75. }

  76. void main()                                                       
  77. {
  78.         uchar i;
  79.         uchar a[5]={0x01,0x02,0x04,0x08,0x10};
  80.         uchar b[5];
  81.         //写EEPROM前不管多少字节(最多512字节)要先擦除整个扇区
  82.         IapEraseSector(IAP_ADDRESS);//擦除EEPROM整个扇区,一个扇区512个字节
  83.         for(i=0;i<5;i++)
  84.         {
  85.                 IapProgramByte(IAP_ADDRESS+i,a[i]);//连续写入5个字节
  86.         }

  87.         for(i=0;i<5;i++)
  88.         {
  89.                 b[i]=IapReadByte(IAP_ADDRESS+i);//连续读取EEPROM中数据另存到b[]
  90.         }
  91.                        
  92.         while(1)
  93.         {
  94.                 for(i=0;i<5;i++)
  95.                 {
  96.                         P1=b[i];//验证b[]中保存的数据
  97.                         delayms(1000);
  98.                 }               
  99.         }
  100. }
复制代码
回复

使用道具 举报

板凳
ID:390416 发表于 2021-5-21 18:18 | 只看该作者
volatile u8 code EEPROM_Flash[512] _at_ 0x4000;

void EEPROM_Wipe512_Drive(u8 AddrH)
{
        IAP_ADDRH=AddrH;
        IAP_CMD=0x03;
        IAP_CONTR|=0x82;
        IAP_TRIG=0x5a;
        IAP_TRIG=0xa5;
}

void EEPROM_Write_Byte_Drive(u8 AddrH,u8 AddrL,u8 Dat)
{
        IAP_ADDRH=AddrH;
        IAP_ADDRL=AddrL;
        IAP_DATA=Dat;
        IAP_CMD=0x02;
        IAP_CONTR|=0x82;
        IAP_TRIG=0x5a;
        IAP_TRIG=0xa5;
}

u8 EEPROM_Read_Byte_Drive(u8 AddrH,u8 AddrL)
{
        u8 Dat;
        IAP_ADDRH=AddrH;
        IAP_ADDRL=AddrL;
        IAP_CMD=0x01;
        IAP_CONTR|=0x82;
        IAP_TRIG=0x5a;
        IAP_TRIG=0xa5;
        Dat=IAP_DATA;
        return Dat;
}
回复

使用道具 举报

地板
ID:451718 发表于 2021-5-22 13:38 | 只看该作者
最初的时候,我用char类型数组来存,后来嫌int类型转换太麻烦, 用了结构体。

void Put_Val(int addr,char number,unsigned char *buf)
{
          unsigned char i;
          Delay10ms();                      //延时
    for (i=0; i<number; i++)         
    {
        IapProgramByte(addr+i, *buf++);
    }
}
//----------------数组的方式---------------------
unsigned char Val[6]={0};
Put_Val(IAP_ADDRESS,8,Val);

//----------------结构体的方式------------------
typedef struct
{
        unsigned char MiniuteP1;
        unsigned char SecondP1;       
        unsigned int  TempP1;
        unsigned long SysTickSec;
}GERVAL;
GERVAL GVal;

Put_Val(IAP_ADDRESS,sizeof(GVal),(unsigned char *)&GVal);

回复

使用道具 举报

5#
ID:858964 发表于 2021-5-22 13:56 | 只看该作者
wulin 发表于 2021-5-20 20:59
给你写一个一看就能明白的示例

请教:有读写MCP4725_EEPROM 的示例代码否?
回复

使用道具 举报

6#
ID:925350 发表于 2021-5-22 14:12 | 只看该作者
和楼主一样的问题,求解
回复

使用道具 举报

7#
ID:608872 发表于 2021-5-25 10:51 | 只看该作者
wulin 发表于 2021-5-20 20:59
给你写一个一看就能明白的示例

写字节的时候,比如第一扇区起始地址0000f,结束地址1ffh,
    IAP_ADDRL = addr;               //设置IAP低地址,addr是不是改成1ffh呢
    IAP_ADDRH = addr >> 8;          //设置IAP高地址,addr是不是改成0000f呢

回复

使用道具 举报

8#
ID:136485 发表于 2021-5-25 11:16 | 只看该作者
给你一段上电读出和写入的代码
d  =IapRead(0x0000);
sum=IapRead(0x0001);
num=IapRead(0x0002);
num=num<<8|IapRead(0x0003);
//speed=IapRead(0x0004);
while (1)
  {
   mode();
   RST();
   if((up)&&(down))
    {
     speed=0;
        }
   if(1==d)
    {
         mode();
     RST();
     //key();
         if(d==0)break;
         if(add)
          {
           count3++;
           //key1=1;
           if(d==0)break;
           if(count3>40000)
            {
                 count3=0;
         num=num-150;
                 if((0==num)||(num>900)){num=150;}
                 _nop_();
             _nop_();
             IapErase(0x0000);//擦除扇区
         IapProgram(0x0000,d);
         IapProgram(0x0001,sum);
         IapProgram(0x0002,num>>8);
         IapProgram(0x0003,num);
回复

使用道具 举报

9#
ID:213173 发表于 2021-5-25 13:32 | 只看该作者
yinnan128 发表于 2021-5-25 10:51
写字节的时候,比如第一扇区起始地址0000f,结束地址1ffh,
    IAP_ADDRL = addr;               //设 ...

以STC15W408AS为例,其EEPROM为5K,分10个扇区。第一扇区地址范围0x0000~0x01ff,第二扇区地址范围0x0200~0x02ff,.......以此类推。各扇区首地址为:0x0000,0x0200,0x0400,0x0800.......。

写数据时,只要不越界,可以指定某扇区的任意地址。操作中通常以首地址+x(x=0~511)的方法。

        写字节的时候,比如第一扇区最后一个地址01ffh

        IAP_ADDRL = addr;               //低8位0xff
        IAP_ADDRH = addr >> 8;          //高8位0x01
回复

使用道具 举报

10#
ID:883031 发表于 2021-5-25 16:48 | 只看该作者
擦除扇区给出起始地址即可,在擦除时地址是自动增加的,知道一个扇区擦完。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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