STM32 SPI标准库与HAL库传输数据的函数对比
1、标准库
/**
* @brief Checks whether the specified SPIx/I2Sx flag is set or not.
* @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
* in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
* @param SPI_I2S_FLAG: specifies the SPI flag to check.
* This parameter can be one of the following values:
* @arg SPI_I2S_FLAG_TXE: Transmit buffer empty flag.
* @arg SPI_I2S_FLAG_RXNE: Receive buffer not empty flag.
* @arg SPI_I2S_FLAG_BSY: Busy flag.
* @arg SPI_I2S_FLAG_OVR: Overrun flag.
* @arg SPI_FLAG_MODF: Mode Fault flag.
* @arg SPI_FLAG_CRCERR: CRC Error flag.
* @arg SPI_I2S_FLAG_TIFRFE: Format Error.
* @arg I2S_FLAG_UDR: Underrun Error flag.
* @arg I2S_FLAG_CHSIDE: Channel Side flag.
* @retval The new state of SPI_I2S_FLAG (SET or RESET).
*/
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx));
assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG));
/* Check the status of the specified SPI flag */
if ((SPIx->SR & SPI_I2S_FLAG) != (uint16_t)RESET)
{
/* SPI_I2S_FLAG is set */
bitstatus = SET;
}
else
{
/* SPI_I2S_FLAG is reset */
bitstatus = RESET;
}
/* Return the SPI_I2S_FLAG status */
return bitstatus;
}
/**
* @brief Transmits a Data through the SPIx/I2Sx peripheral.
* @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
* in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
* @param Data: Data to be transmitted.
* @retval None
*/
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx));
/* Write in the DR register the data to be sent */
SPIx->DR = Data;
}
/**
* @brief Returns the most recent received data by the SPIx/I2Sx peripheral.
* @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
* in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
* @retval The value of the received data.
*/
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx));
/* Return the data in the DR register */
return SPIx->DR;
}
/**
* @brief 发送一个字节的数据
* @param Send_Data:要发送的数据 Timeout:超时时间
* @retval 接收到的数据
*/
uint8_t SPI_1_SendData(uint8_t Send_Data, uint32_t Timeout)
{
uint32_t SPI_Timeout = Timeout;
while (SPI_I2S_GetFlagStatus(SPI_1, SPI_I2S_FLAG_TXE) == RESET)//等待发送缓冲区为空,TXE事件
{
if ((SPI_Timeout--) == 0)
{
DBG_PRINTF("SPI_1发送数据超时!");
return 0;
}
}
SPI_I2S_SendData(SPI_1, Send_Data); //写入数据寄存器,把要写入的数据写入发送缓冲区
SPI_Timeout = Timeout;
while (SPI_I2S_GetFlagStatus(SPI_1, SPI_I2S_FLAG_RXNE) == RESET) //等待接收缓冲区非空,RXNE事件
{
if ((SPI_Timeout--) == 0)
{
DBG_PRINTF("SPI_1接收数据超时!");
return 0;
}
}
//读取数据寄存器,获取接收缓冲区数据
return SPI_I2S_ReceiveData(SPI_1);
}
/**
* @brief 接收一个字节的数据
* @param Send_Data:要发送的数据,读取数据是一般发送0x00或0xFF,根据设备情况而定 Timeout:超时时间
* @retval 返回接收到的数据
*/
uint8_t SPI_1_ReceiveData(uint8_t Send_Data, uint32_t Timeout)
{
return (SPI_1_SendData(Send_Data, Timeout));//读取数据是一般发送0x00或0xFF,根据设备情况而定
}
2、HAL库
/**
* @brief Transmit and Receive an amount of data in blocking mode.
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
* the configuration information for SPI module.
* @param pTxData pointer to transmission data buffer
* @param pRxData pointer to reception data buffer
* @param Size amount of data to be sent and received
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
{
uint16_t initial_TxXferCount;
uint32_t tmp_mode;
HAL_SPI_StateTypeDef tmp_state;
uint32_t tickstart;
#if (USE_SPI_CRC != 0U)
__IO uint32_t tmpreg = 0U;
#endif /* USE_SPI_CRC */
/* Variable used to alternate Rx and Tx during transfer */
uint32_t txallowed = 1U;
HAL_StatusTypeDef errorcode = HAL_OK;
/* Check Direction parameter */
assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
/* Process Locked */
__HAL_LOCK(hspi);
/* Init tickstart for timeout management*/
tickstart = HAL_GetTick();
/* Init temporary variables */
tmp_state = hspi->State;
tmp_mode = hspi->Init.Mode;
initial_TxXferCount = Size;
if (!((tmp_state == HAL_SPI_STATE_READY) || \
((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp_state == HAL_SPI_STATE_BUSY_RX))))
{
errorcode = HAL_BUSY;
goto error;
}
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
{
errorcode = HAL_ERROR;
goto error;
}
/* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
if (hspi->State != HAL_SPI_STATE_BUSY_RX)
{
hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
}
/* Set the transaction information */
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
hspi->pRxBuffPtr = (uint8_t *)pRxData;
hspi->RxXferCount = Size;
hspi->RxXferSize = Size;
hspi->pTxBuffPtr = (uint8_t *)pTxData;
hspi->TxXferCount = Size;
hspi->TxXferSize = Size;
/*Init field not used in handle to zero */
hspi->RxISR = NULL;
hspi->TxISR = NULL;
#if (USE_SPI_CRC != 0U)
/* Reset CRC Calculation */
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
{
SPI_RESET_CRC(hspi);
}
#endif /* USE_SPI_CRC */
/* Check if the SPI is already enabled */
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
{
/* Enable SPI peripheral */
__HAL_SPI_ENABLE(hspi);
}
/* Transmit and Receive data in 16 Bit mode 以16位模式发送和接收数据*/
if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
{
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
{
hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint16_t);
hspi->TxXferCount--;
}
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
{
/* Check TXE flag */
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
{
hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);//发送数据
hspi->pTxBuffPtr += sizeof(uint16_t);
hspi->TxXferCount--;
/* Next Data is a reception (Rx). Tx not allowed */
txallowed = 0U;
#if (USE_SPI_CRC != 0U)
/* Enable CRC Transmission */
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
{
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
}
#endif /* USE_SPI_CRC */
}
/* Check RXNE flag */
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
{
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;//接收数据
hspi->pRxBuffPtr += sizeof(uint16_t);
hspi->RxXferCount--;
/* Next Data is a Transmission (Tx). Tx is allowed */
txallowed = 1U;
}
if (((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY))
{
errorcode = HAL_TIMEOUT;
goto error;
}
}
}
/* Transmit and Receive data in 8 Bit mode 以8位模式发送和接收数据*/
else
{
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
{
*((__IO uint8_t *)&hspi->Instance->DR) = (*hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint8_t);
hspi->TxXferCount--;
}
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
{
/* Check TXE flag */
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
{
*(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr);//发送数据
hspi->pTxBuffPtr++;
hspi->TxXferCount--;
/* Next Data is a reception (Rx). Tx not allowed */
txallowed = 0U;
#if (USE_SPI_CRC != 0U)
/* Enable CRC Transmission */
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
{
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
}
#endif /* USE_SPI_CRC */
}
/* Wait until RXNE flag is reset 等待RXNE标志复位*/
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
{
(*(uint8_t *)hspi->pRxBuffPtr) = hspi->Instance->DR;//接收数据
hspi->pRxBuffPtr++;
hspi->RxXferCount--;
/* Next Data is a Transmission (Tx). Tx is allowed */
txallowed = 1U;
}
if ((((HAL_GetTick() - tickstart) >= Timeout) && ((Timeout != HAL_MAX_DELAY))) || (Timeout == 0U))
{
errorcode = HAL_TIMEOUT;
goto error;
}
}
}
#if (USE_SPI_CRC != 0U)
/* Read CRC from DR to close CRC calculation process */
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
{
/* Wait until TXE flag */
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
{
/* Error on the CRC reception */
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
errorcode = HAL_TIMEOUT;
goto error;
}
/* Read CRC */
tmpreg = READ_REG(hspi->Instance->DR);
/* To avoid GCC warning */
UNUSED(tmpreg);
}
/* Check if CRC error occurred */
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
{
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
/* Clear CRC Flag */
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
errorcode = HAL_ERROR;
}
#endif /* USE_SPI_CRC */
/* Check the end of the transaction */
if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
{
errorcode = HAL_ERROR;
hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
goto error;
}
/* Clear overrun flag in 2 Lines communication mode because received is not read */
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
{
__HAL_SPI_CLEAR_OVRFLAG(hspi);
}
error :
hspi->State = HAL_SPI_STATE_READY;
__HAL_UNLOCK(hspi);
return errorcode;
}

浙公网安备 33010602011771号