/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 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)
{
uint32_t tickstart = 0U;
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();
if (!((hspi->State == HAL_SPI_STATE_READY) || \
((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->State == HAL_SPI_STATE_BUSY_RX))))
{
errorcode = HAL_BUSY;
__HAL_UNLOCK(hspi);
return errorcode;
}
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
{
errorcode = HAL_ERROR;
__HAL_UNLOCK(hspi);
return errorcode;
}
/* 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;
/* Set the number if data at current transfer */
MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
__HAL_SPI_ENABLE(hspi);
if (hspi->Init.Mode == SPI_MODE_MASTER)
{
/* Master transfer start */
SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
}
/* Transmit and Receive data in 32 Bit mode */
if (hspi->Init.DataSize > SPI_DATASIZE_16BIT)
{
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
{
/* Check TXE flag */
if ((hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
{
*((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint32_t);
hspi->TxXferCount --;
}
/* Check RXWNE/EOT flag */
if ((hspi->RxXferCount > 0U) && (hspi->Instance->SR & (SPI_FLAG_RXWNE|SPI_FLAG_EOT)))
{
*((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint32_t);
hspi->RxXferCount --;
}
if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout))
{
/* Call standard close procedure with error check */
SPI_CloseTransfer(hspi);
/* Process Unlocked */
__HAL_UNLOCK(hspi);
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
hspi->State = HAL_SPI_STATE_READY;
return HAL_ERROR;
}
}
}
/* Transmit and Receive data in 16 Bit mode */
else if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
{
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
{
/* Check TXE flag */
if ((hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
{
if ( (hspi->TxXferCount > 1U) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
{
*((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint32_t);
hspi->TxXferCount-=2;
}
else
{
*((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint16_t);
hspi->TxXferCount--;
}
}
/* Check RXWNE/FRLVL flag */
if ((hspi->RxXferCount > 0U) && (hspi->Instance->SR & (SPI_FLAG_RXWNE|SPI_FLAG_FRLVL)))
{
if (hspi->Instance->SR & SPI_FLAG_RXWNE)
{
*((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint32_t);
hspi->RxXferCount-=2;
}
else
{
*((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint16_t);
hspi->RxXferCount--;
}
}
if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout))
{
/* Call standard close procedure with error check */
SPI_CloseTransfer(hspi);
/* Process Unlocked */
__HAL_UNLOCK(hspi);
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
hspi->State = HAL_SPI_STATE_READY;
return HAL_ERROR;
}
}
}
/* Transmit and Receive data in 8 Bit mode */
else
{
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
{
/* check TXE flag */
if ((hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
{
if ((hspi->TxXferCount > 3U) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_03DATA))
{
*((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint32_t);
hspi->TxXferCount-=4;
}
else if ((hspi->TxXferCount > 1U) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA))
{
*((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint16_t);
hspi->TxXferCount-=2;
}
else
{
*((__IO uint8_t *)&hspi->Instance->TXDR) = *((uint8_t *)hspi->pTxBuffPtr);
hspi->pTxBuffPtr += sizeof(uint8_t);
hspi->TxXferCount--;
}
}
/* Wait until RXWNE/FRLVL flag is reset */
if ((hspi->RxXferCount > 0U) && (hspi->Instance->SR & (SPI_FLAG_RXWNE|SPI_FLAG_FRLVL)))
{
if (hspi->Instance->SR & SPI_FLAG_RXWNE)
{
*((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint32_t);
hspi->RxXferCount-=4;
}
else if ((hspi->Instance->SR & SPI_FLAG_FRLVL) > SPI_FRLVL_QUARTER_FULL)
{
*((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint16_t);
hspi->RxXferCount-=2;
}
else
{
*((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
hspi->pRxBuffPtr += sizeof(uint8_t);
hspi->RxXferCount--;
}
}
if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >= Timeout))
{
/* Call standard close procedure with error check */
SPI_CloseTransfer(hspi);
/* Process Unlocked */
__HAL_UNLOCK(hspi);
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
hspi->State = HAL_SPI_STATE_READY;
return HAL_ERROR;
}
}
}
/* Wait for Tx/Rx (and CRC) data to be sent/received */
if (SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_EOT, RESET, tickstart, Timeout) != HAL_OK)
{
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
}
/* Call standard close procedure with error check */
SPI_CloseTransfer(hspi);
/* Process Unlocked */
__HAL_UNLOCK(hspi);
hspi->State = HAL_SPI_STATE_READY;
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
{
return HAL_ERROR;
}
return HAL_OK;
}
这是我从STM32H743的HALL库里面找出来的的SPI发送接收函数,从你进入函数开始到真正将数据开始送出,前面经历了多少校验和查询,这写都会导致时钟延时。下面我贴寄存器方式的你看看,除了定义一个局部变量,之后马上使能SPI,然后会等待一个发送区空,然后立马向数据寄存器写值,此时时钟开始响应,开始发送数据。
u8 SPI2_ReadWriteByte(u8 TxData)
{
u8 RxData=0;
SPI2->CR1|=1<<0; //SPE=1,使能SPI2
SPI2->CR1|=1<<9; //CSTART=1,启动传输
while((SPI2->SR&1<<1)==0); //等待发送区空
*(vu8 *)&SPI2->TXDR=TxData; //发送一个byte,以传输长度访问TXDR寄存器
while((SPI2->SR&1<<0)==0); //等待接收完一个byte
RxData=*(vu8 *)&SPI2->RXDR; //接收一个byte,以传输长度访问RXDR寄存器
SPI2->IFCR|=3<<3; //EOTC和TXTFC置1,清除EOT和TXTFC位
SPI2->CR1&=~(1<<0); //SPE=0,关闭SPI2,会执行状态机复位/FIFO重置等操作
return RxData; //返回收到的数据
}
如果你想更快,初始化的时候就使能SPI,不检测发送区,直接给TXDR送数据,就会更快的让时钟起来。自己测试就知道了。还是那句话,HALL库只能保证你的代码安稳的运行,并检测出在哪出错,但是实时性巨差,是所有方式里面最慢的。如果向高速运行代码,要学会交叉使用,需要快速就自己写寄存器。其他初始化可以用HALL
|