STC DATAFLASH 模拟EEPROM
2015-06-27 04:17
274 查看
今天在写STC的EEPROM,一直调不出来结果,但是还是很有收获的,放上代码,慰劳自己一天的努力,主要还是参考STC的开发手册
我一直调试到现在,发现读数据是ISP_DATA的数据不会改变,始终都是最后一次写入是的值,而且我将写命令或者读命令去掉,还是正常的。我也试了网上其他人的代码,是一样的结果。不知为何。
#include <reg51.h> #include<intrins.h> //定义EEPROM的命令 #define CMD_READ 0x01 #define CMD_WRITE 0x02 #define CMD_ERASE 0x03 //定义ISP_CONTR的等待时间和最高位 #define ENABLE_ISP 0x82 //定义FLASH的基地址 #define Sector_BaseAddr 0x2000 #define Sector_EndAddr 0x2fff #define Sector_BlockSize 16 //定义FLASH的寄存器 sfr ISP_DATA = 0xe2;//数据寄存器,FLASH的读写都通过这个寄存器 sfr ISP_ADDRH = 0xe3;//地址高八位寄存器 sfr ISP_ADDRL = 0xe4;//地址低八位寄存器 sfr ISP_CMD = 0xe5;//命令寄存器 sfr ISP_TRIG = 0xe6;//命令触发寄存器 sfr ISP_CONTR = 0xe7;//控制寄存器 sbit LED = P0^0; //FLASH在擦除是存储已经存在的数据 static unsigned char FLASH_BUFF[Sector_BlockSize]; //ISP的使能 void ISP_Disable() { ISP_CONTR = 0; ISP_CMD = 0; ISP_TRIG = 0; EA = 1; } //ISP的命令触发,只有命令触发了,命令才可以执行 void ISP_Trigger() { EA = 0;//由于下面两个是一起的,所以先把中断关闭 ISP_TRIG = 0x46; ISP_TRIG = 0xb9; _nop_(); } void ISP_Sector_Erase(unsigned short addr) { ISP_CONTR = ENABLE_ISP; ISP_CMD = CMD_ERASE; /* 16的地址先向右移动9位,就只有高7位还保持原来的数据 其余的数据都移出去了,再向左移动9位数据,相当于高8位 只有原来的7位数据,低8位都为零 */ addr = addr & 0xfe00; ISP_ADDRH = addr >> 8; ISP_ADDRL = 0x00; ISP_Trigger(); ISP_Disable(); } //ISP读一个字节 void ISP_Write_Byte(unsigned short beginaddr,unsigned char pBuf) { ISP_CONTR = ENABLE_ISP;//使能控制寄存器 ISP_CMD = CMD_WRITE;//给命令寄存器输入写命令 ISP_ADDRH = beginaddr >> 8;//写入地址 ISP_ADDRL = beginaddr; ISP_Trigger();//命令触发 ISP_DATA = pBuf;//写入数据 ISP_Disable();//开启中断并且初始化 } unsigned char ISP_Read_Byte(unsigned short beginaddr) { ISP_CONTR = ENABLE_ISP; ISP_CMD = CMD_READ; ISP_ADDRH = (unsigned char)(beginaddr >> 8); ISP_ADDRL = (unsigned char)beginaddr; ISP_Trigger(); ISP_Disable(); return ISP_DATA; } void ISP_Read(unsigned short beginaddr,unsigned char* pBuf,unsigned short nBytes) { ISP_CONTR = ENABLE_ISP; ISP_CMD = CMD_READ; ISP_DATA=0; while(nBytes--) { ISP_ADDRH = (unsigned char)(beginaddr >> 8); ISP_ADDRL = (unsigned char)beginaddr; ISP_Trigger(); *pBuf = ISP_DATA; if(ISP_DATA == 1) LED = 0; pBuf++; beginaddr++; } ISP_Disable(); } void ISP_Write_NoCheck(unsigned short beginaddr,unsigned char* pBuf,unsigned short nBytes) { ISP_CONTR = ENABLE_ISP; ISP_CMD = CMD_WRITE; while(nBytes--) { ISP_ADDRH = beginaddr >> 8; ISP_ADDRL = beginaddr; ISP_Trigger(); ISP_DATA = *pBuf; pBuf++; beginaddr++; } ISP_Disable(); } void ISP_Write(unsigned short beginaddr,unsigned char* pBuf,unsigned short nBytes) { /* 判断是否需要擦除,如果需要找到需要擦除的起始地址 将这个扇区之前的数据先读到缓冲区,待会写入的时候再一起写入, 这样防止擦除扇区的时候将之前的数据被擦除 */ unsigned short i = 0; unsigned char sector = (beginaddr - Sector_BaseAddr) / Sector_BlockSize; //得到扇区号 unsigned short offset = beginaddr - (sector * Sector_BlockSize); //得到数据在扇区中的偏移 unsigned short remain = Sector_BlockSize - offset; //得到余留下来的数据位置 if(nBytes < remain) remain = nBytes; while(1) { ISP_Read(beginaddr & 0xfe00,FLASH_BUFF,Sector_BlockSize); //将整个扇区的数据读到缓冲区 for(i = 0; i < remain; i++) //将扇区中的数据一一比对 { if(FLASH_BUFF[offset + i] != 0xff) break; } if(i < remain)//如果中间有不是0xff的地址 { ISP_Sector_Erase(beginaddr); //检测到有没有清空的地方,擦除整个扇区 for(i = 0; i < remain; i++) //将数据拷贝到缓冲区 { FLASH_BUFF[offset + i] = pBuf[i]; } ISP_Write_NoCheck(sector * Sector_BlockSize,FLASH_BUFF,Sector_BlockSize);//将数据全部写入扇区 } else//否则都是干净的地址 { ISP_Write_NoCheck(beginaddr,pBuf,remain);//从后面直接写入,就不需要擦除了 } if(nBytes == remain) break;//如果写入的字节小于一个扇区余留下来的空间,那么一次就写完了,就可以退出来了 else { sector++;//下一个扇区 offset = 0;//偏移为0 pBuf += remain;//已经写了remain个字节,所以要偏移一些 beginaddr += remain;//起始地址也偏移 nBytes -= remain;//字节数减少 if(nBytes > Sector_BlockSize) remain = Sector_BlockSize;//如果不能写入到下一个扇区,那就直接写入一个扇区的数据 else remain = nBytes;//如果能的话,那就直接写入剩余的数据 } } } void main() { unsigned short addr = 0; unsigned char msg[5] = {1,2,3,4,2}; unsigned char mm[5]; ISP_Write_NoCheck(0x2c00,msg,5); //写5个数据 ISP_Read(0x2c00,mm,5);//读出这5个数据 if(mm[0] == 1) { LED = 0; } }
我一直调试到现在,发现读数据是ISP_DATA的数据不会改变,始终都是最后一次写入是的值,而且我将写命令或者读命令去掉,还是正常的。我也试了网上其他人的代码,是一样的结果。不知为何。
相关文章推荐
- 【C#】Winform工具-闪讯下快速分享Wifi(源码)
- java课堂练习之可变参数与卫条件
- Hello World!
- 用于主题检测的临时日志(d092a6e5-a8df-48c7-a5c6-be17d22e1b28 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)
- 欢迎使用CSDN-markdown编辑器
- 多版本office兼容办法
- 微信开发账号要求
- dij最短路优先队列堆的时候,加边
- hdu4445 三分+二分+区间覆盖
- X 主题终结者 WordPress主题[v1.7.5]
- Mobera APP应用展示 WordPress主题[v1.4]
- Buzz 多用途 WordPress主题[v1.10]
- AboutMe 3D简历卡片 WordPress主题[v1.6]
- Jarida 新闻杂志博客 WordPress主题[更新至v2.1.1]
- How To: Integrate AdMob with Cocos2D-x Windows Phone 8 Project
- log log4j配置
- Styles in Windows Phone
- Windows Phone Splash Screen
- canvas 画板
- DomXSS以及绕过浏览器检测机制方法总结