找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机关于EEPROM的读写

[复制链接]
跳转到指定楼层
楼主
ID:1111967 发表于 2024-3-2 14:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
首先我们要知道什么是EEPROM

这里要看自己的单片机EEPROM地址大小和起始地址

主要要用到的寄存器并不多,一个是IAP_CMD(C5H),还有的就是IAP_CONTR(C7H)

然后以下就是通过代码写命令到寄存器最后进行数据操作即可

单片机源程序如下:
  1. #include "STC15F2kxx.h"
  2. #include "stceeprom.h"
  3. #include <intrins.h>
  4. #include <string.h>
  5. #include  "delay.h"


  6. //关闭IAP功能
  7. void IapIdle()         
  8. {
  9.     IAP_CONTR = 0;                 
  10.     IAP_CMD = 0;                  
  11.     IAP_TRIG = 0;                  
  12.     IAP_ADDRH = 0x80;              
  13.     IAP_ADDRL = 0;
  14. }


  15. //擦除指定地址的扇区
  16. void IapEraseSector(WORD addr)
  17. {
  18.     IAP_CONTR = ENABLE_IAP;//使能IAP      
  19.     IAP_CMD = CMD_ERASE; //擦除命令         
  20.     IAP_ADDRL = addr;   //指定地址         
  21.     IAP_ADDRH = addr >> 8;        
  22.     IAP_TRIG = 0x5a;   //命令触发器先写5ah,再写a5h命令才能生效           
  23.                 _nop_();        //等待
  24.     IAP_TRIG = 0xa5;              
  25.     _nop_();                     
  26.     IapIdle();//关闭IAP功能
  27. }


  28. //往指定地址中写入一个字节字符数据
  29. void IapWritecChar(WORD addr, BYTE dat)
  30. {
  31.     IAP_CONTR = ENABLE_IAP;  //使能IAP      
  32.     IAP_CMD = CMD_PROGRAM;  //写命令      
  33.     IAP_ADDRL = addr;     //指定地址         
  34.     IAP_ADDRH = addr >> 8;        
  35.     IAP_DATA = dat;               
  36.     IAP_TRIG = 0x5a;  //命令触发器先写5ah,再写a5h命令才能生效            
  37.           _nop_();
  38.     IAP_TRIG = 0xa5;              
  39.     _nop_();                     
  40.     IapIdle();
  41. }


  42. //往指定地址写入两个字节数据
  43. void IapWriteInt(WORD addr,unsigned int dat)
  44. {
  45.         unsigned char i;
  46.         typedef union  //设置共用体,用char分摊2字节
  47.         {
  48.                 unsigned int dat1;
  49.                 char mchar[2];
  50.         }NEW_DATA;
  51.         NEW_DATA data1;
  52.         data1.dat1 = dat;
  53.         IAP_CONTR = ENABLE_IAP; //使能IAP        
  54.         IAP_CMD = CMD_PROGRAM;   //写命令     
  55.         for(i = 0; i < 2; i++)
  56.         {
  57.     IAP_ADDRL = addr;    //指定地址         
  58.     IAP_ADDRH = addr >> 8;
  59.                 IAP_DATA = data1.mchar[i];
  60.                 IAP_TRIG = 0x5a;  //命令触发器先写5ah,再写a5h命令才能生效            
  61.           _nop_();
  62.     IAP_TRIG = 0xa5;              
  63.     _nop_();   
  64.                 addr++;
  65.         }
  66.          IapIdle();  //关闭IAP功能                  
  67. }

  68. //往指定地址写入四个字节数据
  69. void IapWriteI32(WORD addr, unsigned long dat)  
  70. {
  71.         unsigned char i;
  72.         typedef union//设置共用体,用char分摊4字节
  73.         {
  74.                 unsigned long dat1;
  75.                 char mchar[4];
  76.         }NEW_DATA;
  77.         NEW_DATA data1;
  78.         data1.dat1 = dat;
  79.         
  80.         IAP_CONTR = ENABLE_IAP;  //使能IAP      
  81.         IAP_CMD = CMD_PROGRAM;   //写命令   

  82.         for(i = 0; i < 4; i++)
  83.         {
  84.     IAP_ADDRL = addr;   //指定地址         
  85.     IAP_ADDRH = addr >> 8;
  86.                 IAP_DATA = data1.mchar[i];
  87.                 IAP_TRIG = 0x5a;   //命令触发器先写5ah,再写a5h命令才能生效         
  88.           _nop_();
  89.     IAP_TRIG = 0xa5;            
  90.     _nop_();               
  91.                 addr++;
  92.         }
  93.         IapIdle(); //关闭IAP功能                  
  94. }

  95. /*******************************************************************************
  96. * 函数名  :        Powerlost_data
  97. * 描述    : 断电中断数据写入函数
  98. * 输入    : addr  地址  dat  写入数据
  99. * 输出    : 无
  100. * 返回值  : 无
  101. * 说明    : 为了应对中断函数与主函数循环使用IapWriteI32函数冲突
  102. *******************************************************************************/
  103. void Powerlost_data(WORD addr ,unsigned long dat)
  104. {
  105.         unsigned char i;
  106.         typedef union//设置共用体,用char分摊4字节
  107.         {
  108.                 unsigned long dat1;
  109.                 char mchar[4];
  110.         }NEW_DATA;
  111.         NEW_DATA data1;
  112.         data1.dat1 = dat;
  113.         
  114.         IAP_CONTR = ENABLE_IAP;  //使能IAP      
  115.         IAP_CMD = CMD_PROGRAM;   //写命令   

  116.         for(i = 0; i < 4; i++)
  117.         {
  118.     IAP_ADDRL = addr;   //指定地址         
  119.     IAP_ADDRH = addr >> 8;
  120.                 IAP_DATA = data1.mchar[i];
  121.                 IAP_TRIG = 0x5a;   //命令触发器先写5ah,再写a5h命令才能生效         
  122.           _nop_();
  123.     IAP_TRIG = 0xa5;            
  124.     _nop_();               
  125.                 addr++;
  126.         }
  127.         IapIdle(); //关闭IAP功能
  128. }

  129. //往指定起始地址写入不固定长度的字符串数据
  130. void IapWriteString(WORD addr,BYTE *mString,BYTE n)
  131. {
  132.    unsigned char i;
  133.                 IAP_CONTR = ENABLE_IAP;   //使能IAP        
  134.                 IAP_CMD = CMD_PROGRAM;   //写命令   
  135.    for(i=0; i<n ;i++)
  136.          {
  137.                 IAP_ADDRL = addr; //指定地址      
  138.                 IAP_ADDRH = addr >> 8;
  139.                 IAP_DATA = mString[i];
  140.                 IAP_TRIG = 0x5a;   //命令触发器先写5ah,再写a5h命令才能生效           
  141.                 _nop_();
  142.                 IAP_TRIG = 0xa5;              
  143.                 _nop_();
  144.                 addr++;                 
  145.           }
  146.          IapIdle();   //关闭IAP功能                  
  147. }

  148. //向指定地址读取一个字节的字符数据
  149. char IapReadChar(WORD addr)
  150. {
  151.                 BYTE dat;
  152.     IAP_CONTR = ENABLE_IAP;  //使能IAP         
  153.     IAP_CMD = CMD_READ;    //读命令         
  154.     IAP_ADDRL = addr;  //指定地址              
  155.     IAP_ADDRH = addr >> 8;         
  156.     IAP_TRIG = 0x5a; //命令触发器先写5ah,再写a5h命令才能生效               
  157.                 _nop_();
  158.     IAP_TRIG = 0xa5;               
  159.     _nop_();                        
  160.     dat = IAP_DATA;               
  161.     IapIdle();  //关闭IAP功能                    

  162.     return dat;                    
  163. }
  164. //向指定地址读取两个字节的数字数据
  165. unsigned int IapReadInt(WORD addr)
  166. {
  167.         unsigned int dat;
  168.         unsigned char i;
  169.         typedef union        //设置共用体,用char分摊2字节
  170.         {
  171.                 unsigned int dat1;
  172.                 char mchar[2];
  173.         }NEW_DATA;        
  174.         NEW_DATA data1;  
  175.         IAP_CONTR = ENABLE_IAP;  //使能IAP         
  176.         IAP_CMD = CMD_READ;      //读命令         
  177.         for(i = 0; i < 2; i++)
  178.         {
  179.     IAP_ADDRL = (addr + i);  //指定地址      
  180.     IAP_ADDRH = ((addr + i) >> 8);
  181.     IAP_TRIG = 0x5a;   //命令触发器先写5ah,再写a5h命令才能生效           
  182.                 _nop_();
  183.     IAP_TRIG = 0xa5;              
  184.     _nop_();                     
  185.     data1.mchar[i]= IAP_DATA;
  186.         }
  187.         IapIdle();   //关闭IAP功能
  188.         dat = data1.dat1;
  189.         return dat;
  190. }


  191. //向指定地址读取四个字节的数字数据
  192. unsigned long IapReadI32(WORD addr)
  193. {
  194.         unsigned long dat;
  195.         unsigned char i;
  196.         typedef union//设置共用体,用char分摊4字节
  197.         {
  198.                 unsigned long dat1;
  199.                 char mchar[4];
  200.         }NEW_DATA;
  201.         NEW_DATA data1;
  202.         IAP_CONTR = ENABLE_IAP;  //使能IAP         
  203.         IAP_CMD = CMD_READ;      //读命令

  204.                      
  205.         for(i = 0; i < 4; i++)
  206.         {
  207.     IAP_ADDRL = (addr + i); //指定地址      
  208.     IAP_ADDRH = ((addr + i) >> 8);
  209.     IAP_TRIG = 0x5a;  //命令触发器先写5ah,再写a5h命令才能生效            
  210.                 _nop_();
  211.     IAP_TRIG = 0xa5;              
  212.     _nop_();                     
  213.     data1.mchar[i] = IAP_DATA;   
  214.         }
  215.         IapIdle();//关闭IAP功能
  216.         dat = data1.dat1;
  217.         return dat;
  218. }


  219. //向指定地址读取不定长度的字符串数据
  220. void IapReadString(WORD addr,BYTE *mString, BYTE n)
  221. {
  222.   unsigned char i;
  223.         memset(mString,0,strlen(mString));
  224.         IAP_CONTR = ENABLE_IAP;   //使能IAP               
  225.   IAP_CMD = CMD_READ;      //读命令                              
  226.   for(i = 0; i < n; i++)
  227.         {
  228.     IAP_ADDRL = (addr + i);  //指定地址        
  229.     IAP_ADDRH = ((addr + i) >> 8);  
  230.     IAP_TRIG = 0x5a;   //命令触发器先写5ah,再写a5h命令才能生效            
  231.                 _nop_();
  232.     IAP_TRIG = 0xa5;               
  233.     _nop_();                              
  234.     mString[i] = IAP_DATA;         
  235.         }
  236.         IapIdle();//关闭IAP功能
  237. }
复制代码


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

使用道具 举报

沙发
ID:41656 发表于 2024-3-9 11:49 | 只看该作者
小数据可以这样写分开几个字节几个字节的写,不过建议写数据可以使用一个结构体把数据和校验数据都写进去,使用指针,存储根据结构体数据sizeof结果直接写入,读取时通过结构体数据大小一次性读取并做校验,我现在数据量小CRC8做校验,要是数据量大可以考虑CRC16或32
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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