1、原因
最近在看安富萊的bsp教程,關(guān)于usart的部分使用了fifo的管理,但是安富萊的教程中,F(xiàn)IFO管理部分都是自己寫的,而stm32官方的hal庫里面,關(guān)于usart發(fā)送部分是有HAL_UART_Transmit_IT可以以中斷的方式發(fā)送數(shù)據(jù)的。我現(xiàn)在的疑惑就是,我只使用安富萊的fifo管理部分,將發(fā)送部分交給hal庫的函數(shù)進行處理,可不可是實現(xiàn)和安富萊bsp教程相同的功能。
2、函數(shù)解析
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->pTxBuffPtr = pData;
huart->TxXferSize = Size;
huart->TxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Process Unlocked */
__HAL_UNLOCK(huart);
/* Enable the UART Transmit data register empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
該段代碼是stm32f4的HAL_UART_Transmit_IT函數(shù)代碼。再該段代碼中,1、先判斷了發(fā)送是否處于忙。2、進行上鎖。3、設(shè)置隊列,并設(shè)置相關(guān)參數(shù)4、解鎖5、開始發(fā)送通過上面一段代碼,可以知道該函數(shù)是非阻塞的發(fā)送方式,其方式是在串口中斷中進行管理實現(xiàn)的隊列數(shù)據(jù)發(fā)送。詳細說明如下:
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
/* UART in mode Transmitter ------------------------------------------------*/
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
{
UART_Transmit_IT(huart);
return;
}
/* UART in mode Transmitter end --------------------------------------------*/
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
{
UART_EndTransmit_IT(huart);
return;
}
}
在函數(shù)里面由這兩段代碼進行判斷,其中標(biāo)志位說明如下
由標(biāo)志位我們可以知道,當(dāng)一組數(shù)據(jù)未傳輸完成時,TXE數(shù)據(jù)會置1,如果開啟了中斷,那么tc也會置1,但是根據(jù)if語句的先后順序,會先執(zhí)行UART_Transmit_IT(huart);函數(shù),在該函數(shù)路面,會再次對dr寄存器進行數(shù)據(jù)寫入。寫入完成后,會對tc位置0。當(dāng)所有的數(shù)據(jù)都發(fā)送完成之后,UART_Transmit_IT(huart);不會再次寫入dr寄存器,程序進入UART_EndTransmit_IT(huart);函數(shù),觸發(fā)HAL_UART_TxCpltCallback(huart);中斷。
修改思路
接下來的問題就簡單了,我們只需要在安富萊的發(fā)送開始函數(shù)改成HAL_UART_Transmit_IT()即可,然后在發(fā)送中斷里面寫fifo的發(fā)送即可。