⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eeprom.c

📁 关于SPI接口的eeprom的读写
💻 C
字号:
#include "2407.h"
#include "eeprom.h"  

unsigned int Spi_Data,SpiRdData,SpiStatus,SpiBsyloop;//SpiBsyloop决定忙状态的循环判断
unsigned int SpiRdflag,SpiWrflag,SpiWrEnflag,SpiBsyflag,SpiendFlag,SpiTxCnt,SpiRxCnt; 
                        //SPI要靠自己判别发送和接受      Spi发送的字节数 接受的字节数
                        //设置了写使能、写数据、读数据、忙状态等标志
                        //根据标志决定中断中的操作,自己等计划中的中断 
unsigned int SpiErrflag; //忙标志长期有效后的报错标志                                  
unsigned int SpiTxData[1000],SpiRxData[1000]; //建立的写数组和读数组  
unsigned int SpiTxNum,SpiRxNum;//批量读写计数标志
unsigned int * SpiWrPtr;  //写数据指针指向将写的源数组
unsigned int * SpiRdPtr;  //读数据指针指向将读目的数组   
unsigned int E2promErr;
void SpiInit(void)
{
	MCRB |= 0x1c;   //SPI相应I/O口基本功能,ste使用IO口控制
	MCRB &= 0xffdf;
	PCDATDIR|=0x2020;//ste设置为输出且置位
	SPICCR = 0x07; //8位传送方式
	SPICTL = 0x1f;//使能覆盖中断
	SPIBRR = 0x004f;//波特率500k
	SPIPRI = 0x10;	 //高优先级中断SPI、不受仿真影响 ; 0x40低优先级\一旦进入仿真spi停止
	SPICCR = 0x87;  //处于准备状态
	SpiRdflag=0;
	SpiWrflag=0;
	SpiWrEnflag=0;
	SpiBsyflag=0;
	SpiErrflag=0;
	SpiendFlag=0;
	SpiTxCnt=0;
	SpiRxCnt=0;
	E2promErr=0;
}

//以下几个子程序,在字节传送的过程中是不允许中断的,这个需要特别处理
void SpiWordWr(unsigned int WrAddress, unsigned int WrData)
{  //单字的写入       写入地址             写入数据
   //无论读写都是把SPI当成2048个16位存储空间,因为不能跨16个字(32字节)写
   //Spi内部是4096*8的空间,32字节一页,最多一页的写入,不能跨页写,可以跨页读
  unsigned int i=0;
  unsigned int j; 
  SpiBsy();
  SpiWrEnflag=1;  
  PCDATDIR|=0x2020;//置IOPC5为输出高
  PCDATDIR&=0xffdf;//置STE为输出低
  //for(j=0;j<5;j++);//延时500ns  
  //while(SpiendFlag==0);
  SPITXBUF = 0x0600; 
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
  SpiendFlag=0;
  //for(j=0;j<5;j++);//延时500ns  
  PCDATDIR|=0x2020;//置IOPC5为输出高
  for(j=0;j<5;j++);//延时500ns 
   
  PCDATDIR&=0xffdf;//置STE为输出低
  //for(j=0;j<1;j++);//延时500ns  
  SpiWrflag=1;
  SpiTxCnt=5;
  
  SPITXBUF =0x0200;
  while(SpiendFlag==0);//&&(SpiErrflag==0));
  SpiendFlag=0;
  SPITXBUF =(WrAddress<<1)&0xff00;  
  //while((SPISTS & 0x20) == 0x20);
  while(SpiendFlag==0);//&&(SpiErrflag==0));
  SpiendFlag=0;
  SPITXBUF =(WrAddress<<9)&0xff00;
  //while((SPISTS & 0x20) == 0x20);
  while(SpiendFlag==0);//&&(SpiErrflag==0));
  SpiendFlag=0;
  SPITXBUF=(WrData<<8)&0xff00;
  
  //while((SPISTS & 0x20) == 0x20);
  while(SpiendFlag==0);//&&(SpiErrflag==0));
  SpiendFlag=0;
  SPITXBUF=WrData;
  //while((SpiWrflag==1)&&(SpiErrflag==0));
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
  SpiendFlag=0;
  //while((SpiWrflag==1)&&(SpiErrflag==0)&&(i++<2000))//等待一次忙判断结束
  //   for(j=0;j<100;j++);
  
  //for(j=0;j<5;j++);//延时500ns  
  PCDATDIR|=0x2020;//置STE为输出高
  for(j=0;j<5;j++);//延时500ns  
	 //if(SpiWrflag==1)
	 // {
	 //  SpiErrflag=1;
	 //  SpiWrflag=0;
	 // }
}

void SpiBatWr(unsigned int WrAddress, unsigned int BatWrlength, unsigned int* WrData)
{    //批量写              写入spi地址              写入长度      将被写入的数组指针
     //Spi内部是4096*8的空间,32字节一页,最多一页的写入,不能跨页写,可以跨页读
     //无论读写都是把SPI当成2048个16位存储空间,因为不能跨16个字(32字节)写
     //内部处理后实现透明无缝写入
  unsigned int i,j,k,SpiAddress,No16Times;
  unsigned int m=0;
  SpiWrPtr=WrData;
  SpiAddress=2*WrAddress;
  No16Times=0;
  k=WrAddress&0xf;//处理跨界写
  if(k!=0)
  {
    No16Times=1;
    k=16-k;
  }  
  SpiTxNum=BatWrlength; 
  i=0; 
  while(i<SpiTxNum)
  {
      SpiBsy();
      PCDATDIR|=0x2020;//置STE输出高
	  PCDATDIR&=0xffdf;//置STE输出低
	  //for(j=0;j<5;j++);//延时500ns  
	  SpiWrEnflag=1;  
	  SPITXBUF = 0x0600; 
	  //while((SpiWrEnflag==1)&&(SpiErrflag==0));
	  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
	  SpiendFlag=0;
	  //for(j=0;j<1;j++);//延时500ns  
      PCDATDIR|=0x2020;//置IOPC5为输出高
      for(j=0;j<5;j++);//延时500ns  
      
      PCDATDIR&=0xffdf;//置STE为输出低
      //for(j=0;j<1;j++);//延时500ns  
	  if(No16Times==0)
	  	  if(SpiTxNum-i>=16)
	  	  k=16;              //够一页的处理
	      else  k=SpiTxNum-i;//不够一页的处理
	   else
	         {
	           No16Times=0;  //起始地址非16整数倍的处理
	           if(k>SpiTxNum)
	             k=SpiTxNum; //起始地址非16整数倍但数据长度短于该页的空余的处理
	         }    
	  SpiWrflag=1;
	  SpiTxCnt=2*k+3;
	  SPITXBUF =0x0200;
	  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
	  SpiendFlag=0;
	  SPITXBUF =SpiAddress&0xff00; 
	  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
	  SpiendFlag=0;
	  //while((SPISTS & 0x20) == 0x20); 
	  SPITXBUF =(SpiAddress<<8)&0xff00;
	  //while((SPISTS & 0x20) == 0x20); 
	  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
	  SpiendFlag=0;
	  for(j=0;j<k;j++)
	  {
		  SPITXBUF=((*SpiWrPtr)<<8)&0xff00;
		  //while((SPISTS & 0x20) == 0x20);
		  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
		  SpiendFlag=0;
		  SPITXBUF=*SpiWrPtr;
		  
		  //while((SPISTS & 0x20) == 0x20);
		  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
		  SpiendFlag=0;
		  SpiWrPtr++;
		  i++;
	  }	
	 //while((SpiWrflag)&&(SpiErrflag==0)); 
	 //while((SpiWrflag==1)&&(SpiErrflag==0)&&(m++<2000))//等待一次忙判断结束
	 //for(j=0;j<100;j++);
	 
	 //for(j=0;j<1;j++);//延时500ns  
	 PCDATDIR|=0x2020;//置IOPC5为输出高
	 for(j=0;j<5;j++);//延时500ns 
	 
	 if(SpiWrflag==1)
	  {
	   SpiErrflag=1;
	   SpiWrflag=0;
	  }
	 SpiAddress=SpiAddress+2*k;
 } 
}

void SpiWordRd(unsigned int RdAddress,unsigned int *RdData )
{ //单字内容的读            读入的spi地址 读的数据目的地址
  //Spi内部是4096*8的空间,32字节一页,最多一页的写入,不能跨页写,可以跨页读
  //无论读写都是把SPI当成2048个16位存储空间
  unsigned int i=0;
  unsigned int j;
  SpiBsy();
  SpiWrflag=1;
  SpiRdflag=1;
  SpiTxCnt=3;
  SpiRxNum=1;
  SpiRdPtr=RdData;
  //while((SPISTS & 0x20) == 0x20);
  PCDATDIR|=0x2020;//置STE输出高
  PCDATDIR&=0xffdf;//置STE输出低
  //for(j=0;j<1;j++);//延时500ns  
  SPITXBUF =0x0300;
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
  SpiendFlag=0;
  SPITXBUF =(RdAddress<<1)&0xff00;  
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
  SpiendFlag=0;
  //while((SPISTS & 0x20) == 0x20);
  SPITXBUF =(RdAddress<<9)&0xff00;
  //while((SPISTS & 0x20) == 0x20); 
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能  
  SpiendFlag=0;
  SPITXBUF=Spi_Data;
  //while((SPISTS & 0x20) == 0x20);
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
  SpiendFlag=0;
  SPITXBUF=Spi_Data;
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
  SpiendFlag=0;
  //while((SpiRdflag==1)&&(SpiErrflag==0));
  //while((SpiRdflag==1)&&(SpiErrflag==0)&&(i++<2000))//等待一次忙判断结束
   //for(j=0;j<100;j++);
  //for(j=0;j<5;j++);//延时500ns  
  PCDATDIR|=0x2020;//置IOPC5为输出高
  for(j=0;j<5;j++);//延时500ns  
  //if(SpiRdflag==1)
  //{
  // SpiErrflag=1;
  // SpiRdflag=0;
  //}
} 

void SpiBatRd(unsigned int RdAddress,unsigned int BatRdLenth,unsigned int *RdData)
{ //批量读                 读入spi地址        读入的长度        读入的目的指针
  //无论读写都是把SPI当成2048个16位存储空间
  unsigned int i,j,SpiAddress;
  unsigned int k=0;
  SpiBsy();
  SpiAddress=2*RdAddress;
  SpiRdPtr=RdData;
  SpiRxNum=BatRdLenth;
  SpiWrflag=1;
  SpiRdflag=1;
  SpiTxCnt=3;
  //while((SPISTS & 0x20) == 0x20);
  PCDATDIR|=0x2020;//置STE输出高
  PCDATDIR&=0xffdf;//置STE输出低
  //for(j=0;j<1;j++);//延时500ns  
  SPITXBUF =0x0300;
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
  SpiendFlag=0;
  SPITXBUF =(SpiAddress)&0xff00; 
  //while((SPISTS & 0x20) == 0x20);
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
  SpiendFlag=0;
  SPITXBUF =(SpiAddress<<8)&0xff00;
  //while((SPISTS & 0x20) == 0x20); 
  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
  SpiendFlag=0;
  for(i=0;i<SpiRxNum*2;i++)
  {   
	  SPITXBUF=Spi_Data;
	  //while((SPISTS & 0x20) == 0x20);
	  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
	  SpiendFlag=0;
	  SPITXBUF=Spi_Data;
	  //while((SPISTS & 0x20) == 0x20);
	  while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
	  SpiendFlag=0;
  }
  //while((SpiRdflag==1)&&(SpiErrflag==0));
  //while((SpiRdflag==1)&&(SpiErrflag==0)&&(k++<2000))//等待一次忙判断结束
   //for(j=0;j<100;j++);
  //for(j=0;j<1;j++);//延时500ns  
  PCDATDIR|=0x2020;//置IOPC5为输出高
  for(j=0;j<5;j++);//延时500ns   
  //if(SpiRdflag==1)
  //{
  // SpiErrflag=1;
  // SpiRdflag=0;
  //}
} 

void SpiBsy(void)
{ 
  unsigned int i=0,j; 
  SpiBsyflag=1;
  while(SpiBsyflag==1)//&&(i++<200))  //一直判断下去,除非存储器写不忙
  {
   SpiBsyloop=1;
   SpiTxCnt=2;
   PCDATDIR|=0x2020;//置STE输出高
   PCDATDIR&=0xffdf;//置STE输出低
   //for(j=0;j<1;j++);//延时500ns  
   SPITXBUF =0x0500;
   while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
   SpiendFlag=0;
   SPITXBUF =0x0500;   
   while(SpiendFlag==0);//&&(SpiErrflag==0));//写使能
   SpiendFlag=0;
   //while((SpiBsyloop==1)&&(SpiErrflag==0)&&(i++<2000))//等待一次忙判断结束
   //for(j=0;j<100;j++);
   //for(j=0;j<1;j++);//延时500ns  
   PCDATDIR|=0x2020;//置IOPC5为输出高
   for(j=0;j<5;j++);//延时500ns  
  } 
   
  //if(SpiBsyflag==1)
  //{
  // SpiErrflag=1;
  // SpiBsyflag=0;
  //}
}

void   SpiIntSub(void)
{       
        unsigned int SpiTemp;
	    if(SpiWrEnflag)
	       SpiWrEnflag=0;
	    else   if(SpiWrflag) 
					{
					 SpiTxCnt--;
					 if(SpiTxCnt==0)
					 	 {
					 	  SpiWrflag=0;
					 	  SpiRxCnt=0;
					 	 } 
					} 
					else if(SpiRdflag) 
							{
							 if((SpiRxCnt&0x01)==0)
							 {
							  SpiRdData=SPIRXBUF&0xff; 
							  SpiRxCnt++;
        					} 
							 else {
							       // SpiRdData= (SpiRdData<<8)+(SPIRXBUF&0xff);
							       SpiTemp=SPIRXBUF&0xff;
							       SpiRdData= SpiRdData+(SpiTemp<<8);
							       *SpiRdPtr=SpiRdData;
							       SpiRdPtr++;
							       SpiRxCnt++;
							       if((SpiRxCnt>>1)>=SpiRxNum)//接受完毕
							       SpiRdflag=0;
							      } 
							} 
							else if(SpiBsyflag)
							     {
							      SpiTxCnt--;
					              if(SpiTxCnt==0)
					              { 
								      SpiStatus=SPIRXBUF&0xff;
								      if((SpiStatus&0x01)==0)
								         SpiBsyflag=0;
								      SpiBsyloop=0; //一次忙判断的结束
								   }   
							     } 
		if((SPISTS & 0x80) == 0x80) //有覆盖现象发生,清除
		{
		    SPISTS=SPISTS&0x7f;
			SpiErrflag=1;
			SPICCR = SPICCR&0x7f;
			SPICCR = SPICCR|0x80;
		}		
		Spi_Data=SPIRXBUF;
		SpiendFlag=1;	
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -