×
单片机 > 单片机程序设计 > 详情

Cortex-M3 (NXP LPC1788)之EEPROM存储器

发布时间:2020-08-21 发布时间:
|
        EEPROM是一种非易失性存储器,主要用于存储相对少量的数据,如存储一些系统的配置信息。通过系统的EEPROM控制模块可以轻松的进行EERPOM的存储控制。

        要正确使用EPPROM需要配置掉电寄存器EEPWRDWN确定EEPROM的工作模式,配置EEPROM时钟分频器寄存器,使EPPROM工作在375KHZ。下面对EPPROM的读和写数据进行介绍。

        EEPROM存储器的访问有三种操作方式:读、写、擦除/编程。对EPPROM中写数据分成两个单独的操作:写和擦除/编程。第一步写操作并不是真正把数据写入EPPROM的存储介质中,而只是更新被称作“页寄存器”的临时数据寄存器。只有执行下一步”擦除/编程“操作才会真正地更新非易失存储器。LPC1788共有4K的片内EPPROM,其中EPPROM的每一页等于页寄存器大小为64Byte,总共有64页。大小正好是64*64=4096Byte=4K。首先我们指定的位数,如8、16或者32位,将数据写入页寄存器,页内的地址偏移由EEPROM地址寄存器的第6位决定。如果需要往页寄存器写入一串数据,写完第一个数据后,页内的偏移地址会自动增加,我们只需把要操作的下一个数据填入EEPROM写数据寄存器即可。当页寄存器的64个字节被写满,必须进行编程操作,将数据写入到EEPROM的存储介质。然后更新页寄存器的偏移地址。

        对于EEPROM的读操作,首先要向地址寄存器写入一个12位的地址,高6位为页的偏移,即我们需要读哪个页寄存器。低6位为页内的偏移,即我们需要读当前页的哪个字节。读操作也可以自动的对地址寄存器做后递增,这样就可以对EEPROM存储器进行连续的操作而无需每次读数据都写入一个新地址。

        下面的程序将信息写入EEPROM后读出通过串口打印显示

 
  1. #include "LPC1788_REG.h"  
  2. #include "uart.h"  
  3.   
  4. #define rEECMD          (*(volatile unsigned*)(0x00200080))  
  5. #define rEEADDR         (*(volatile unsigned*)(0x00200084))  
  6. #define rEEWDATA        (*(volatile unsigned*)(0x00200088))  
  7. #define rEERDATA        (*(volatile unsigned*)(0x0020008C))  
  8. #define rEEWSTATE       (*(volatile unsigned*)(0x00200090))  
  9. #define rEECLKDIV       (*(volatile unsigned*)(0x00200094))  
  10. #define rEEPWRDWN       (*(volatile unsigned*)(0x00200098))  
  11.   
  12. #define rEEINTEN        (*(volatile unsigned*)(0x00200FE4))  
  13. #define rEEINTCLR       (*(volatile unsigned*)(0x00200FD8))  
  14. #define rEEINTSET       (*(volatile unsigned*)(0x00200FDC))  
  15. #define rEEINTSTAT      (*(volatile unsigned*)(0x00200FE0))  
  16. #define rEEINTSTATCLR   (*(volatile unsigned*)(0x00200FE8))  
  17. #define rEEINTSTATSET   (*(volatile unsigned*)(0x00200FEC))  
  18.   
  19. #define EEPROM_PAGE_SIZE 64  
  20. void Init_EEPROM(void);  
  21. void Write_EEPROM(unsigned char page_num, unsigned char page_offset, char* data, unsigned int count);  
  22. void Read_EEPROM(unsigned char page_num, unsigned char page_offset, char* data, unsigned int count);  
  23.   
  24. char read_buffer[];  
  25. char write_buffer[] = {"\n\r\  
  26. \t - Name: Nuncle.lee \n\r\  
  27. \t - QQ: 23610603 \n\r\  
  28. \t - Email: nuncle.lee@gmail.com\n\r"};  
  29.   
  30. int main(void)  
  31. {     
  32.     Init_Uart2();  
  33.     Init_EEPROM();  
  34.       
  35.       
  36.     Write_EEPROM(0, 0, write_buffer, sizeof(write_buffer));  
  37.     Write_EEPROM(sizeof(write_buffer)/64, sizeof(write_buffer)%64, '\0', 1);  
  38.       
  39.     Read_EEPROM(0, 0, read_buffer, sizeof(write_buffer)+1);  
  40.       
  41.     Uart2SendS(read_buffer);  
  42.   
  43.     return 0;  
  44. }  
  45.   
  46. void Init_EEPROM(void)  
  47. {  
  48.     unsigned int val=0;  
  49.       
  50.     rEEPWRDWN = 0;  //不处于掉电模式  
  51.     rEECLKDIV = (CCLK/375000)-1;    //设置一个375KHZ的EEPROM时钟  
  52.       
  53.     val  = ((((CCLK / 1000000) * 15) / 1000) + 1);      //配置等待状态时间  
  54.     val |= (((((CCLK / 1000000) * 55) / 1000) + 1) <
  55.     val |= (((((CCLK / 1000000) * 35) / 1000) + 1) <
  56.     rEEWSTATE = val;  
  57. }  
  58. void Write_EEPROM(unsigned char page_num, unsigned char page_offset, char* data, unsigned int count)  
  59. {  
  60.     unsigned int i;  
  61.       
  62.     rEEADDR = (page_offset&0x3f);   //确定开始写的页内偏移地址  
  63.     for(i=0; i
  64.     {  
  65.         rEECMD = 0x3;               //8位写操作  
  66.         rEEWDATA = *(data+i);  
  67.         while(!(rEEINTSTAT & (0x1<<26)));   //等待写操作完成  
  68.         page_offset++;  
  69.           
  70.         if(page_offset >= EEPROM_PAGE_SIZE)     //如果当前页写满了64Byte 则启动 编程操作  
  71.         {  
  72.             rEEINTSTATCLR = 0x1<<28;  
  73.             rEEADDR = (page_num&0x3F)<<6;  
  74.             rEECMD = 0x6;   //擦除编程  
  75.             while(!(rEEINTSTAT & (0x1<<28)));   //等待编程完成  
  76.               
  77.             page_offset = 0;  
  78.             page_num++;     //写满一页,准备写下一页  
  79.             rEEADDR = 0;    //写满一页,从页的开始写  
  80.         }  
  81.         else if(i==count-1)                 //如果要写入EPPROM的数据写完成,启动编程操作  
  82.         {  
  83.             rEEINTSTATCLR = 0x1<<28;  
  84.             rEEADDR = (page_num&0x3F)<<6;  
  85.             rEECMD = 0x6;   //擦除编程  
  86.             while(!(rEEINTSTAT & (0x1<<28)));  
  87.         }  
  88.     }  
  89. }  
  90.   
  91. void Read_EEPROM(unsigned char page_num, unsigned char page_offset, char* data, unsigned int count)  
  92. {  
  93.     unsigned int i;  
  94.     rEEADDR = (page_num&0x3F)<<6|page_offset&0x3F;      //确定读数据的起始位置,包括页偏移和页内的偏移  
  95.     rEECMD = 0x1<<3;                                    //8位读,地址自动递增模式  
  96.     for(i=0; i
  97.     {  
  98.         while(!(rEEINTSTAT & (0x1<<26)));               //等待上一次读数据完成  
  99.         *(data+i) = rEERDATA;  
  100.         page_offset++;  
  101.           
  102.         if(page_offset >= EEPROM_PAGE_SIZE)             //如果当前页64Byte读完,准备读下一页  
  103.         {  
  104.             page_offset = 0;  
  105.             page_num++;  
  106.             rEEADDR = (page_num&0x3F)<<6|page_offset&0x3F;    
  107.             rEECMD = 0x1<<3;  
  108.         }  
  109.     }  
  110. }  

 

程序的执行结果如下图

程序中,sizeof关键字计算出字符数组的大小,并不包含字符串的结束标志‘\0’。因此还需在sizeof(write_buffer)的位置写入字符串的结束标志。读取时读sizeof(write_buffer)+1个字节,才能正确的通过串口打印数据。当然,也可以自己指定串口打印字符的个数,而不用字符串结束标志去判断。

关键字:Cortex-M3  NXP  LPC1788)  EEPROM存储器 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会