最近在学习SPI做了一个小实验,从机接收主机的数据并将其返回给主机,算是个SPI的回环实验吧
但是这个实验并没有实际应用的意义,在实际应用中SPI从机发送数据需要配合DMA,片选NSS使用。因为今天只是简单测试一下,就不要DMA了
SPI主机想必大家都有了解,但是SPI从机可能接触的比较少,比如像我之前就没接触过这方面的代码配置。之前一直奇怪SPI从机是怎么产生时钟,后来查阅资料才发现,时钟信号只有SPI主机才能产生,从机也只能在主机产生时钟的时候收发数据。
话不多说,我们来看主机代码
uint8_t cmd1 = 0xF1;
GPIO_InitType GPIO_InitStructure;
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_6|GPIO_PIN_5|GPIO_PIN_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF0_SPI1;
GPIO_InitPeripheral(SPI_MASTER_GPIO, &GPIO_InitStructure);
SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
SPI_InitStructure.SpiMode = SPI_MODE_MASTER;
SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS;
SPI_InitStructure.CLKPOL = SPI_CLKPOL_LOW;
SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
SPI_InitStructure.NSS = SPI_NSS_SOFT;
SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_16;
SPI_InitStructure.FirstBit = SPI_FB_MSB;
SPI_InitStructure.CRCPoly = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Enable(SPI1, ENABLE);
SPI_I2S_TransmitData(SPI1,cmd1);
Delay(200);
for(i=1; i<100 ;i++)
{
while(SPI_I2S_GetStatus(SPI1, SPI_I2S_TE_FLAG) == RESET){}
SPI_I2S_TransmitData(SPI1,i);
}
这里我们从机利用接收中断来回主机数据
SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
SPI_InitStructure.SpiMode = SPI_MODE_SLAVE;
SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS;
SPI_InitStructure.CLKPOL = SPI_CLKPOL_LOW;
SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
SPI_InitStructure.NSS = SPI_NSS_SOFT;
SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_8;
SPI_InitStructure.FirstBit = SPI_FB_MSB;
SPI_InitStructure.CRCPoly = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_I2S_EnableInt(SPI1, SPI_I2S_INT_RNE, ENABLE);
SPI_Enable(SPI1, ENABLE);
这里需要注意SPI主机从机配置要保持一致
void GPIO_Configuration(void)
{
GPIO_InitType GPIO_InitStructure;
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF0_SPI1;
GPIO_InitPeripheral(SPI_MASTER_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_5|GPIO_PIN_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Input;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF0_SPI1;
GPIO_InitPeripheral(SPI_MASTER_GPIO, &GPIO_InitStructure);
}
GPIO配置时SCK脚配置为输入模式
void SPI1_IRQHandler(void)
{
if (SPI_I2S_GetIntStatus(SPI1, SPI_I2S_INT_RNE) != RESET)
{
test = SPI_I2S_ReceiveData(SPI1);
SPI1->DAT = 0;
SPI_I2S_TransmitData(SPI1,test);
SPI_I2S_ClrITPendingBit(SPI1,SPI_I2S_INT_RNE);
}
}
OK,软件配置完成,接下来我们用逻辑分析仪抓一下数据看从机收发的数据是否一致
可以看到从机收发数据一致,测试pass
下次可以SPI从机通过DMA方式发送数据
|