参考文章:1. http://t.csdn.cn/FT6Mg
2. http://t.csdn.cn/ejFIQ
今天用STM32F1的HAL库开发遇到一个奇怪的问题,在主函数循环调用中用串口1的DMA请求,将内存中的数据发送给串口,无论延迟Delay开了多大,始终只能发送一次DMA数据。后来在网上查阅大佬的资料终于有了思路。
废话不多说,先上代码:
在 stm32f1xx_hal_uart.c 文件中找到HAL_UART_Transmit_DMA()函数实现,在解锁操作__HAL_UNLOCK;后添加代码:huart -> gState = HAL_UART_STATE_READY; 编译以后运行完美解决。而且在低延迟的高速while循环中反复调用串口DMA请求,都可以运行。
HAL_UART_Transmit_DMA()函数实现修改:(也就多加了一行代码而已[doge])
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
uint32_t *tmp;
/* 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; //修改串口的工作状态为Busy
/* Set the UART DMA transfer complete callback */
huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt;
/* Set the UART DMA Half transfer complete callback */
huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt;
/* Set the DMA error callback */
huart->hdmatx->XferErrorCallback = UART_DMAError;
/* Set the DMA abort callback */
huart->hdmatx->XferAbortCallback = NULL;
/* Enable the UART transmit DMA channel */
tmp = (uint32_t *)&pData;
HAL_DMA_Start_IT(huart->hdmatx, *(uint32_t *)tmp, (uint32_t)&huart->Instance->DR, Size);
/* Clear the TC flag in the SR register by writing 0 to it */
__HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
/* Process Unlocked */
__HAL_UNLOCK(huart);
huart -> gState = HAL_UART_STATE_READY; //这一句官方好像给落下了???
/* Enable the DMA transfer for transmit request by setting the DMAT bit
in the UART CR3 register */
SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
简要分析:每当调用一次HAL_UART_Transmit_DMA()都会先进行一次串口状态的判断:if (huart->gState == HAL_UART_STATE_READY) 如果串口处于READY状态,则开始本次的DMA传输,否则会返回一个BUSY状态:
else
{
return HAL_BUSY;
}
当第一次调用HAL_UART_Transmit_DMA()时,串口处于READY状态,于是进行DMA传输,注意,在DMA传输过程中,会将串口从READY状态改为发送BUSY状态(软件修改):huart->gState = HAL_UART_STATE_BUSY_TX;但是在DMA完成本次传输工作以后,并没有将串口从发送BUSY状态改回READY状态,一开始我认为可能硬件自动修改该标志,但是不确定,还没有翻参考手册,如果有知道的大佬烦请指教!因此这里我索性添加一句代码软件修改该状态:huart -> gState = HAL_UART_STATE_READY;文章来源:https://www.toymoban.com/news/detail-536708.html
这样就能保证每次调用完HAL_UART_Transmit_DMA()函数后,串口的状态均为READY,为下一次的串口发送DMA请求做准备。文章来源地址https://www.toymoban.com/news/detail-536708.html
到了这里,关于通过修改HAL_UART_Transmit_DMA()函数,解决串口发送DMA只能发送一次的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!