单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:607|回复: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. }
复制代码


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

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

Powered by 单片机教程网