本人使用SPI通讯经验不多,当初是为了实现DSP与FPGA之间的通讯,DSP在SPI通讯中作主机,SPI数据位数为16位模式。SPI的原理我不多说了,我对这种通讯的方式理解,这是一种高速通讯,同时还有个特点,就是接收了多少位数据的同时意味着发送了多少位数据,比如你希望接收2个字节的数据,那么你应该发送2个字节的数据,发送数据就意味着接收数据,接收数据就意味着发送数据,关键看你需要的是接收还是发送的数据。嘿嘿,有点像绕口令。
本文提出的SPI通讯也是
基于FIFO的轮询方式,这种SPI函数要么在DSP架构中的主中断,或者主循环中运行。
关于SPI的CS引脚,我这里用的是SPI自带的CS引脚,简而言之,不是普通的IO引脚,为啥我不用普通的IO引脚,是因为我用了之后,我用示波器观看,SPI的CLK信号还没结束,充当CS的IO引脚已经拉高了,然后我增加延时,效果不显著,这延时会随不同SPI读写的数据长度的改变而改变,实在太麻烦了,最终我没有选择这种CS引脚的使用方式。如果使用普通的IO引脚,大部分人是这么做的,在SPI函数之前将充当CS的IO引脚拉低,然后在在SPI函数之后将充当CS的IO引脚拉高,我用的也是这种办法,但会出现上述的问题。
所以我干脆把GPIO配置成SPI的CS引脚,让SPI自动控制,不过我这种用法,SPI读写的字节数不过超过FIFO的级数,可怜的DSP28069,只有4级FIFO,而DSP28377D有16级的FIFO。
代码:
void InitSpia(void)
{
SpiaRegs.SPICCR.bit.SPISWRESET = 1; //Clear the SPI Software Reset bit to force
//the SPI to the reset state
SpiaRegs.SPICCR.bit.SPILBK = 0; //loopback mode
SpiaRegs.SPICCR.bit.SPICHAR = 0xf; //data format 16bit mode
SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1; //spi master
SpiaRegs.SPICTL.bit.TALK = 1; //enable transmit
SpiaRegs.SPICTL.bit.CLK_PHASE = 0; //transmit on falling edge,receives on rising
SpiaRegs.SPICCR.bit.CLKPOLARITY = 1; //When no SPI data is sent, SPICLK is at high
//level
SpiaRegs.SPIBRR =0x0001; //SPI波特率=20M/4 =5Mhz;
SpiaRegs.SPIPRI.bit.FREE = 1; // 自由运行
DELAY_US(10);
SpiaRegs.SPIFFTX.all=0xE040;//使能FIFO;清除发送中断标志位;禁止FIFO发送中断;
//发送中断级别定义为0;
SpiaRegs.SPIFFRX.all=0x204f;//清除FF溢出标志位;清除溢出接受中断标志位;禁止
//FF接受中断;接受中断级别为16;
SpiaRegs.SPIFFCT.all=0x0;//SPITXBUF到移位寄存器传送不延迟; sysclock/4
SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1;
}
void InitSpib(void)
{
SpibRegs.SPICCR.bit.SPISWRESET = 1; //Clear the SPI Software Reset bit to force
//the SPI to the reset state
SpibRegs.SPICCR.bit.SPILBK = 0; //loopback mode
SpibRegs.SPICCR.bit.SPICHAR = 0xf; //data format 16bit mode
SpibRegs.SPICTL.bit.MASTER_SLAVE = 1; //spi master
SpibRegs.SPICTL.bit.TALK = 1; //enable transmit
SpibRegs.SPICTL.bit.CLK_PHASE = 0; //transmit on falling edge,receives on rising
SpibRegs.SPICCR.bit.CLKPOLARITY = 1; //When no SPI data is sent, SPICLK is at high
//level
SpibRegs.SPIBRR =0x0001; //SPI波特率=20M/4 =5Mhz;
SpibRegs.SPIPRI.bit.FREE = 1; // 自由运行
DELAY_US(10);
SpibRegs.SPIFFTX.all=0xE040;//使能FIFO;清除发送中断标志位;禁止FIFO发送中断;
//发送中断级别定义为0;
SpibRegs.SPIFFRX.all=0x204f;//清除FF溢出标志位;清除溢出接受中断标志位;禁止
//FF接受中断;接受中断级别为16;
SpibRegs.SPIFFCT.all=0x0;//SPITXBUF到移位寄存器传送不延迟; sysclock/4
SpibRegs.SPIFFRX.bit.RXFIFORESET = 1;
}
void InitSpiaGpio(void)
{
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0; // Enable pull-up on GPIO16 (SPISIMOA)
GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0; // Enable pull-up on GPIO17 (SPISOMIA)
GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0; // Enable pull-up on GPIO18 (SPICLKA)
GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0; // Enable pull-up on GPIO19 (SPISTEA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3; // Asynch input GPIO16 (SPISIMOA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3; // Asynch input GPIO17 (SPISOMIA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3; // Asynch input GPIO18 (SPICLKA)
GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 3; // Asynch input GPIO19 (SPISTEA)
GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // Configure GPIO16 as SPISIMOA
GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // Configure GPIO17 as SPISOMIA
GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // Configure GPIO18 as SPICLKA
GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // Configure GPIO19 as SPISTEA
// GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 0; //gpio = gpio
// GpioCtrlRegs.GPADIR.bit.GPIO19 = 1; //output
// GpioDataRegs.GPASET.bit.GPIO19 = 1; //high
// GpioDataRegs.GPACLEAR.bit.GPIO19 =1;//low
EDIS;
}
void InitSpibGpio(void)
{
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO24 = 0; // Enable pull-up on GPIO24 (SPISIMOB)
GpioCtrlRegs.GPAPUD.bit.GPIO25 = 0; // Enable pull-up on GPIO25 (SPISOMIB)
GpioCtrlRegs.GPAPUD.bit.GPIO26 = 0; // Enable pull-up on GPIO26 (SPICLKB)
GpioCtrlRegs.GPAPUD.bit.GPIO27 = 0; // Enable pull-up on GPIO27 (SPISTEB)
GpioCtrlRegs.GPAQSEL2.bit.GPIO24 = 3; // Asynch input GPIO24 (SPISIMOB)
GpioCtrlRegs.GPAQSEL2.bit.GPIO25 = 3; // Asynch input GPIO25 (SPISOMIB)
GpioCtrlRegs.GPAQSEL2.bit.GPIO26 = 3; // Asynch input GPIO26 (SPICLKB)
GpioCtrlRegs.GPAQSEL2.bit.GPIO27 = 3; // Asynch input GPIO27 (SPISTEB)
GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 3; // Configure GPIO24 as SPISIMOB
GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 3; // Configure GPIO25 as SPISOMIB
GpioCtrlRegs.GPAMUX2.bit.GPIO26 = 3; // Configure GPIO26 as SPICLKB
GpioCtrlRegs.GPAMUX2.bit.GPIO27 = 3; // Configure GPIO27 as SPISTEB
// GpioCtrlRegs.GPAMUX2.bit.GPIO27 = 0; //gpio = gpio
// GpioCtrlRegs.GPADIR.bit.GPIO27 = 1; //output
// GpioDataRegs.GPASET.bit.GPIO27 = 1; //high
// GpioDataRegs.GPACLEAR.bit.GPIO27 = 1;//low
EDIS;
}
写函数:
void SendSpi_N(Uchar dev,Uint16 *sndbuf,Uint16 cnt)
{
Uint16 i=0,num=cnt,len;
volatile struct SPI_REGS *p;
switch(dev)
{
case Spi_a:
p = &SpiaRegs;
break;
case Spi_b:
p = &SpibRegs;
break;
default:
p = &SpiaRegs;
break;
}
while(num-i >= 4)
{
p->SPIFFRX.bit.RXFIFORESET = 1;
p->SPITXBUF = sndbuf[i++];
p->SPITXBUF = sndbuf[i++];
p->SPITXBUF = sndbuf[i++];
p->SPITXBUF = sndbuf[i++];
while(p->SPIFFRX.bit.RXFFST<4);
p->SPIFFRX.bit.RXFIFORESET = 0;
}
len = num-i;
p->SPIFFRX.bit.RXFIFORESET = 1;
for(;iSPITXBUF = sndbuf[i++];
}
while(p->SPIFFRX.bit.RXFFSTSPIFFRX.bit.RXFIFORESET = 0;
num=0;
p->SPIFFRX.bit.RXFIFORESET = 1;
}
读函数:
void ReadSpi_N(Uchar dev,Uint16 *rcvbuf,Uint16 cnt)
{
Uint16 i=0,j=0,num=cnt,len;
volatile struct SPI_REGS *p;
switch(dev)
{
case Spi_a:
p = &SpiaRegs;
break;
case Spi_b:
p = &SpibRegs;
break;
default:
p = &SpiaRegs;
break;
}
while(num-i>=4)
{
p->SPITXBUF = 0x0101;
p->SPITXBUF = 0x0101;
p->SPITXBUF = 0x0101;
p->SPITXBUF = 0x0101;
while(p->SPIFFRX.bit.RXFFST<4);
rcvbuf[i++] = p->SPIRXBUF & 0xFFFF;
rcvbuf[i++] = p->SPIRXBUF & 0xFFFF;
rcvbuf[i++] = p->SPIRXBUF & 0xFFFF;
rcvbuf[i++] = p->SPIRXBUF & 0xFFFF;
}
len = num-i;
for(j=0;jSPITXBUF = 0;
}
while(p->SPIFFRX.bit.RXFFSTSPIFFRX.bit.RXFFST>0)
{
rcvbuf[i++] = p->SPIRXBUF & 0xFFFF;
}
}