这里我按照自己的想法稍微做了一点点的改动就测试成功了,接下来可以加上判断条件来有目的地返回数据。
先上一份我修改成库函数版本的程序吧。
PS:发现用软件判断CS,是比较慢的,数据会后移不少,放在中断里直接置标志位比较快捷。能用硬件NSS就还是用上吧,从机模式下很好用,基本不出错。
[mw_shl_code=c,true]u8 RxBuf[10];
u8 spi_cnt=0;
main(void)
{
......
SPI_SLAVE_Init();
SPI_SLAVE_SendByte(0x12);//SPI首字节0x12,作为从机标识
__enable_interrupt();
......
}
void SPI_SLAVE_Init(void)
{
SPI_DeInit();
/* 初始化SPI , 从机和主机的相位有效沿一定要一致*/
SPI_Init(SPI_FIRSTBIT_MSB, SPI_BAUDRATEPRESCALER_2,SPI_MODE_SLAVE,\
SPI_CLOCKPOLARITY_LOW, SPI_CLOCKPHASE_1EDGE, \
SPI_DATADIRECTION_2LINES_FULLDUPLEX, SPI_NSS_SOFT, 0x07);
SPI_ITConfig(SPI_IT_RXNE,ENABLE);
SPI_NSSInternalSoftwareCmd(DISABLE);//产生SSI从机信号,也可放在外部中断里来使能从机中断
SPI_Cmd(ENABLE);
}
u8 SPI_SLAVE_SendByte(u8 byte)//把while判断非空标志全部去掉,不然等待时间太长会错帧,判断等待交给主机做
{
/* Loop while DR register in not emplty */
// while (SPI_GetFlagStatus( SPI_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_SendData(byte);
/* Wait to receive a byte */
// while (SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_ReceiveData();
}
//SPI从机中断
INTERRUPT_HANDLER(SPI_IRQHandler, 10)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
uint8_t Rx_byte,spi_head;
// if(GPIO_ReadInputPin(GPIOD, GPIO_PIN_3)==0)//确认CS脚拉低的这个判断太慢了,总是出错,另谋他法吧!
// {
Rx_byte = SPI_SLAVE_SendByte(0x36);//设置下一个字节,同时读回主机当前CLK下的字节
if((spi_cnt == 0)&&((Rx_byte == 0xef)||(Rx_byte == 0x7e))) //首字为0xef或者0x7e,就认为是有效包
{
spi_head = 1;
}
if(spi_head) //在有效包内的话就将读回的字节放入数组
{
RxBuf[spi_cnt] = Rx_byte; //注意,首字会在这个数组里
spi_cnt += 1; //地址+1
}
if(spi_cnt==10) //包满归零
{
spi_head=0;
spi_cnt=0;
SPI_SLAVE_SendByte(0x12);//设置下一轮发送的首字节0x12
}
// }
}
[/mw_shl_code]
|