1、原因
最近在看安富莱的bsp教程,关于usart的部分使用了fifo的管理,但是安富莱的教程中,FIFO管理部分都是自己写的,而stm32官方的hal库里面,关于usart发送部分是有HAL_UART_Transmit_IT可以以中断的方式发送数据的。我现在的疑惑就是,我只使用安富莱的fifo管理部分,将发送部分交给hal库的函数进行处理,可不可是实现和安富莱bsp教程相同的功能。
2、函数解析
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函数代码。再该段代码中,1、先判断了发送是否处于忙。2、进行上锁。3、设置队列,并设置相关参数4、解锁5、开始发送通过上面一段代码,可以知道该函数是非阻塞的发送方式,其方式是在串口中断中进行管理实现的队列数据发送。详细说明如下:
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;
}
}
在函数里面由这两段代码进行判断,其中标志位说明如下
由标志位我们可以知道,当一组数据未传输完成时,TXE数据会置1,如果开启了中断,那么tc也会置1,但是根据if语句的先后顺序,会先执行UART_Transmit_IT(huart);函数,在该函数路面,会再次对dr寄存器进行数据写入。写入完成后,会对tc位置0。当所有的数据都发送完成之后,UART_Transmit_IT(huart);不会再次写入dr寄存器,程序进入UART_EndTransmit_IT(huart);函数,触发HAL_UART_TxCpltCallback(huart);中断。
修改思路
接下来的问题就简单了,我们只需要在安富莱的发送开始函数改成HAL_UART_Transmit_IT()即可,然后在发送中断里面写fifo的发送即可。