借鉴其他文章的问题描述:
最近遇到一个小问题,感觉很有意思便记下来分享一下 ,顺便也为日后类似的问题提供点思路:
使用stm32串口发送数据 ,串口是单线半双工模式,要求数据发送前串口变成发送模式,发送完后立即变回接收模式,发送操作使用DMA来发送,程序开了串口中断和DMA中断,串口中断主要是用于接收与解析数据,DMA中断是想用于操作串口收发模式切换,发现DMA发送时最后一个数据老是发不出来。
搜索发现,这篇文章:(165条消息) stm32 usart 单线半双工串口 DMA发送 最后一个字节发不出来问题_张十三的博客的博客-CSDN博客_usart_halfduplexcmd
查看后发现文章方法,并不适用于当前的HAL库
直接上解决方法:
1.在stm32f1xx_it.c文件中增加回调函数,DMA全部发送完成,使用的也是串口的回调:
/* USER CODE BEGIN 1 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
//__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_TC);
//使能接收功能。每次接收前要调用此函数
HAL_HalfDuplex_EnableReceiver(&huart1);
}
/* USER CODE END 1 */
2.找到stm32f1xx_hal_uart.c文件,并找到如下函数,增加一行命令:
/**
* @brief DMA UART transmit process complete callback.
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* DMA Normal mode*/
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
huart->TxXferCount = 0x00U;
/* Disable the DMA transfer for transmit request by setting the DMAT bit
in the UART CR3 register */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);//增加这行
SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
}
/* DMA Circular mode */
else
{
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Tx complete callback*/
huart->TxCpltCallback(huart);
#else
/*Call legacy weak Tx complete callback*/
HAL_UART_TxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
}
问题解决,猜测原因,大概率是uart的TC寄存器,由于某种原因,导致在发送中间被置位,但是在发送中没有复位的命令。