最近在学习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方式发送数据
|