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