概述
SPI是一种高速,全双工,主从模式,同步串行的通信方式。
我们认为SPI为四线机制,把NSS也算上。
SCK用于输出时钟,只有主设备才能输出时钟。MOSI为主发从收。MISO为主收从发。NSS为片选线,用来对从设备进行选择。
STM32F103ZET6与SPI


这里输出均为复用推挽输出,输入随便。后续我们使用软件片选为通用推挽输出。
SPI协议理解

当片选线哪一个被拉低,相当于选择了哪一个从设备。
SPI是基于SCK边沿的工作模式。比如空闲状态默认0,第一个跳变来读数据,第二个跳变写数据。这里主和从必须同时收发实现全双工,本质就是数据交换。
时钟极性:这个对应的就是空闲时的状态时1还是0
时钟相位:其为0,先读后写。为1,先写后读。
极性和相位组合起来就是四种模式。

SPI内部结构

我们对其进行简化

本质其实就是把数据放到移位寄存器,随后像个滚轮一样的交换数据。然后DR寄存器放入移位寄存器,包括读取,这些都靠寄存器的一些标志来进行控制。
代码讲解
HAL_SPI_Transmit
cpp
while (hspi->TxXferCount > 0U)
{
/* Wait until TXE flag is set to send data */
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
{
*((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint8_t);
hspi->TxXferCount--;
}
else
{
/* Timeout management */
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
{
hspi->State = HAL_SPI_STATE_READY;
__HAL_UNLOCK(hspi);
return HAL_TIMEOUT;
}
}
本质就是不断往DR寄存器放入参数。