柳德伟的个人世界 https://bbs.21ic.com/?2461 [收藏] [复制] [RSS] “四十不惑”,说的是人生的道理已经参悟得差不多了,明白自己能干啥不能干啥,能够准确的定位自己,干自己喜欢干的事! ...

日志

SPI接口eeprom的驱动。

已有 1623 次阅读2008-2-3 07:17 |系统分类:存储器

#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; 
}


路过

鸡蛋

鲜花

握手

雷人

发表评论 评论 (1 个评论)

访客KOFr37 2008-5-17 20:22
找了半天了,终于这里看到了,谢谢博主