STC89C52RC内部EEPROM的读写

来源:互联网 发布:游族网络敖厂长 编辑:程序博客网 时间:2024/04/30 05:20

转自:http://xouou.iteye.com/blog/1815427


STC单片机的内部EEPROM是用DATAFLASH模拟出来的,不是真正的EEPROM存储器,不能用普通的方法来操作
下面是一些注意点:
1.字节写之前要先将这个字节所在扇区的其它有效数据读取到RAM暂存(这步不是必须的)
2.暂存完之后再对整个扇区(512字节)进行擦除操作,擦拭完后,整个扇区每个地址中数据都变成0xFF
3.将欲写入的N个字节数据,用字节写函数写入EEPROM
4.将暂存到RAM的其它有用的EEPROM值再用字节写函数写回EEPROM
5.STC用FLASH模拟出来的EEPROM的字节写功能只能将1变成0,而不能将0变成1,
  只有扇区擦除后数据才是全1,
  例如:在地址0x21f0处第1次写11010110,第2次写111010,读出结果是这2个值的相与10010
         所以如果一个地址处的值不是0xff时写入新的数据是不对的,要先执行扇区擦除,变为0xff,
         对于单个字节的写入,我们可以先检查该地址处的数据是否为0xff,是的话就不用擦除扇区了

----------------------------------------------------------------------
STC89C52单片机内部EEPROM 的读写过程
1  配置ISP_CONTR寄存器,使能第7位ISPEN,让ISP_IAP功能生效,并配置低3位的等待时间
2  写指令: 读/写/擦除扇区 这3个命令
3  赋值: ISP_ADDRH和ISP_ADDRL的地址值
4  关闭总中断EA,因为下面要写的2个触发指令必须是连续操作的,不能被中断
5  执行公用的  ISP_IAP 触发指令,触发后读写操作才能进行
6  打开中断 EA, 关闭ISP_IAP功能:清相关寄存器

C代码  收藏代码
  1. #include "my51.h"  
  2.   
  3. /******************定义命令字节******************/         
  4. #define read_cmd     0x01                   //字节读数据命令       
  5. #define wirte_cmd    0x02                   //字节编程数据命令       
  6. #define erase_cmd    0x03                   //扇区擦除数据命令                 
  7.     
  8. /****************特殊功能寄存器声明****************/    
  9. sfr ISP_DATA = 0xe2;     
  10. sfr ISP_ADDRH = 0xe3;       
  11. sfr ISP_ADDRL = 0xe4;     
  12. sfr ISP_CMD = 0xe5;     
  13. sfr ISP_TRIG = 0xe6;        
  14. sfr ISP_CONTR = 0xe7;  
  15.   
  16. /*定义Flash 操作等待时间及允许IAP/ISP/EEPROM 操作的常数******************/  
  17. //#define enable_waitTime 0x80 //系统工作时钟<30MHz 时,对IAP_CONTR 寄存器设置此值  
  18. //#define enable_waitTime 0x81 //系统工作时钟<24MHz 时,对IAP_CONTR 寄存器设置此值  
  19. //#define enable_waitTime 0x82  //系统工作时钟<20MHz 时,对IAP_CONTR 寄存器设置此值  
  20. #define enable_waitTime 0x83 //系统工作时钟<12MHz 时,对IAP_CONTR 寄存器设置此值  
  21. //#define enable_waitTime 0x84 //系统工作时钟<6MHz 时,对IAP_CONTR 寄存器设置此值  
  22.     
  23.       
  24. void ISP_IAP_disable(void)                  //关闭ISP_IAP  
  25. {     
  26.     EA=1;                                   //恢复中断  
  27.     ISP_CONTR = 0x00;       
  28.     ISP_CMD = 0x00;        
  29.     ISP_TRIG = 0x00;                                               
  30. }  
  31.   
  32. void ISP_IAP_trigger()                       //触发   
  33. {     
  34.     EA=0;                                    //下面的2条指令必须连续执行,故关中断             
  35.     ISP_TRIG = 0x46;                         //送触发命令字0x46       
  36.     ISP_TRIG = 0xB9;                         //送触发命令字0xB9       
  37. }  
  38.          
  39.   
  40. void ISP_IAP_readData(u16 beginAddr, u8* pBuf, u16 dataSize) //读取数据  
  41. {  
  42.     ISP_DATA=0;                               //清零,不清也可以  
  43.     ISP_CMD = read_cmd;                       //指令:读取  
  44.     ISP_CONTR = enable_waitTime;              //开启ISP_IAP,并送等待时间   
  45.     while(dataSize--)                         //循环读取  
  46.     {  
  47.         ISP_ADDRH = (u8)(beginAddr >> 8);     //送地址高字节        
  48.         ISP_ADDRL = (u8)(beginAddr & 0x00ff); //送地址低字节  
  49.         ISP_IAP_trigger();                  //触发  
  50.         beginAddr++;                        //地址++  
  51.         *pBuf++ = ISP_DATA;                 //将数据保存到接收缓冲区  
  52.     }  
  53.     ISP_IAP_disable();                      //关闭ISP_IAP功能  
  54. }         
  55.      
  56. void ISP_IAP_writeData(u16 beginAddr,u8* pDat,u16 dataSize) //写数据      
  57. {             
  58.     ISP_CONTR = enable_waitTime;                //开启ISP_IAP,并送等待时间         
  59.     ISP_CMD = wirte_cmd;                        //送字节编程命令字  
  60.     while(dataSize--)  
  61.     {  
  62.         ISP_ADDRH = (u8)(beginAddr >> 8);       //送地址高字节         
  63.         ISP_ADDRL = (u8)(beginAddr & 0x00ff);   //送地址低字节             
  64.         ISP_DATA = *pDat++;                     //送数据         
  65.         beginAddr++;   
  66.         ISP_IAP_trigger();                      //触发  
  67.     }            
  68.     ISP_IAP_disable();   //关闭                                        
  69. }      
  70.           
  71. void ISP_IAP_sectorErase(u16 sectorAddr)        //扇区擦除  
  72. {             
  73.     ISP_CONTR = enable_waitTime;                //开启ISP_IAP;并送等待时间         
  74.     ISP_CMD = erase_cmd;                        //送扇区擦除命令字           
  75.     ISP_ADDRH = (u8)(sectorAddr >> 8);            //送地址高字节         
  76.     ISP_ADDRL = (u8)(sectorAddr & 0X00FF);      //送地址低字节             
  77.     ISP_IAP_trigger();                          //触发  
  78.     ISP_IAP_disable();                          //关闭ISP_IAP功能           
  79. }  
  80.       
  81. void main()                                     //测试  
  82. {     
  83.     u8 buf[3]={0};                              //接收数据缓冲区  
  84.     u8 dat[5]={b(111010),b(1001),b(1),b(1011),b(1110)};//我写成二进制是为观察led灯     
  85.     ISP_IAP_sectorErase(0x2000);                //扇区擦除,一块512字节         
  86.     ISP_IAP_writeData(0x21f0,dat,sizeof(dat));  //写EEPROM             
  87.     ISP_IAP_readData(0x21f0,buf,sizeof(buf));   //读取  
  88.     P1=buf[2];//在地址0x21f0处第1次写11010110,第2次写111010,读出结果是这2个值的相与10010  
  89.     while(1); //所以如果一个地址处的值不是0xff时写入新的数据是不对的,要先擦除为0xff   
  90. }  

 

C代码  收藏代码
  1. #ifndef _MY51_H  
  2. #define _MY51_H  
  3. #include <reg52.h>  
  4. //#include <math.h>  
  5. #include <intrins.h>  
  6. #include <stdio.h>  
  7. #include "mytype.h"  
  8.   
  9. /*************二进制输入宏****************************/  
  10. #ifndef _LongToBin_  
  11. #define _LongToBin_  
  12. #define LongToBin(n) \               
  13. (                    \   
  14. ((n >> 21) & 0x80) | \   
  15. ((n >> 18) & 0x40) | \   
  16. ((n >> 15) & 0x20) | \   
  17. ((n >> 12) & 0x10) | \   
  18. ((n >> 9)  & 0x08) | \   
  19. ((n >> 6)  & 0x04) | \   
  20. ((n >> 3)  & 0x02) | \   
  21. ((n ) & 0x01)        \   
  22. )  
  23. #define  bin(n)  LongToBin(0x##n##l)  
  24. #define  BIN(n)  bin(n)  
  25. #define  B(n)    bin(n)  
  26. #define  b(n)    bin(n)             
  27. #endif  
  28.   
  29. /*************单个数据位的置位宏*********************/  
  30. #ifndef   _BIT_  
  31. #define   _BIT_   
  32. #define   BIT(n)   (1<<n)  
  33. #define   bit(n)   BIT(n)  
  34. #endif  
  35.   
  36. #define high    1   //高电平  
  37. #define low     0   //低电平  
  38.   
  39. #define led P1      //灯总线控制  
  40.   
  41. sbit led0=P1^0;     //8个led灯,阴极送低电平点亮  
  42. sbit led1=P1^1;  
  43. sbit led2=P1^2;  
  44. sbit led3=P1^3;  
  45. sbit led4=P1^4;  
  46. sbit led5=P1^5;  
  47. sbit led6=P1^6;  
  48. sbit led7=P1^7;   
  49. sbit ledLock=P2^5;  //led锁存的状态,0锁定 ,1不锁定  
  50.   
  51. sbit beep=P2^3;     //蜂鸣器  
  52.   
  53. void delayms(u16 ms);  
  54. //void delayXus(u8 us); //函数执行(8+6x)个机器周期, 即t=(8+6x)*1.085  
  55. /////////////////////////////////////////////////////////////////////////////  
  56.   
  57.   
  58. #endif 

0 0
原创粉丝点击