你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32CubeMX的一个疑似串口DMA传输Bug

[复制链接]
yjnwjs 提问时间:2016-12-25 23:04 /
用STM32CubeMX V4.17.0 新建了一个串口DMA传输工程,同时使用接收和发送传输,目标器件为STM32F103ZET。STM32CubeMX完成了所有初始化工作。用户的工作是定义了缓存uint8_t uart1TxDmaBuffer[TX_DMA_BUFFER_SIZE],然后调用DMA发送函数HAL_UART_Receive_DMA(huart, (uint8_t *)uart1RxDmaBuffer, (uint16_t)RX_DMA_BUFFER_SIZE)完成发送。但是使用过程中发现,HAL_UART_Receive_DMA只工作一次便拒绝再次工作。即使将它放进while循环,复位后只发送一次便不再工作。按理来说,DMA中断是打开的,发送完毕执行中断服务函数,应该会将状态恢复到READY,下次用户调用便再次发送才对。分析代码发现,DMA发送的最终调用函数为UART_DMATransmitCplt:
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)     
{
  UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
  /* DMA Normal mode*/
  if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
  {
    huart->TxXferCount = 0;

    /* 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_ENABLE_IT(huart, UART_IT_TC);
  }
  /* DMA Circular mode */
  else
  {
    HAL_UART_TxCpltCallback(huart);
  }
}

在Normal模式下,该函数的工作只是清除些标志,没有调回调函数。关键在于,该函数没有将串口的状态从HAL_UART_STATE_BUSY_TX清除为HAL_UART_STATE_BUSY_READY,于是HAL_UART_Receive_DMA判断串口状态为HAL_UART_STATE_BUSY_TX,便拒绝再次发送。后修改代码(红色为增加部分)为:
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)     
{
  UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
  /* DMA Normal mode*/
  if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
  {
    huart->TxXferCount = 0;

    /* 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);
               
                /* Check if a transmit process is ongoing or not */
   if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
    {
      huart->State = HAL_UART_STATE_BUSY_RX;
    }
    else
    {
      huart->State = HAL_UART_STATE_READY;
    }
    /* Enable the UART Transmit Complete Interrupt */   
    __HAL_UART_ENABLE_IT(huart, UART_IT_TC);
  }
  /* DMA Circular mode */
  else
  {
    HAL_UART_TxCpltCallback(huart);
  }
}

工作正常。
收藏 2 评论7 发布时间:2016-12-25 23:04

举报

7个回答
5265325 回答时间:2016-12-26 10:25:51
wjandsq 回答时间:2016-12-26 11:34:18
1.103的HAL库要修改一次才行。
2.中断函数不应该这么写的,最好是每个中断写一个。
3.回调函数要自己实现的,最好不要改人家的。
4.DMA用起来,HAL库没有Stdperiph 库灵活了。
wjandsq 回答时间:2016-12-26 11:35:20
可以参考F4的HAL库,stm32cubemx软件要升级为4.18.0版本。
当幸福来敲men 回答时间:2017-2-14 13:58:47
为什么我改了之后还是不正常,楼主能分享个例程吗?
当幸福来敲men 回答时间:2017-2-14 15:57:12
只要 在cube配置时开启串口中断就可以用了,不用添加任何代码
无帝老三 回答时间:2017-9-28 14:21:50
本帖最后由 无帝老三 于 2017-9-28 14:31 编辑

目前使用f4的HAL库 cubemax 4.18
不开启uart中断,
DMA发送一次后huart->gState = HAL_UART_STATE_BUSY_TX
就再也不会变成HAL_UART_STATE_READY了

开启uart中断后,就会执行HAL_UART_IRQHandler,进入去执行到最后
UART_EndTransmit_IT里面会执行huart->gState = HAL_UART_STATE_READY;

之前想少开一个串口中断,看来是画蛇添足了

SlamDunk 回答时间:2019-11-30 21:17:21
最近也在研究这个,
发表下个人意见:
  /* Enable the UART Transmit Complete Interrupt */   
    __HAL_UART_ENABLE_IT(huart, UART_IT_TC);
最后不是打开TCIE中断了吗?传输完成后,UART_TC_FLAG应该已经置位,加之中断TCIE打开,
最后会进入串口中断处理函数,执行到UART_EndTransmit_IT(huart);
该函数里有:
__HAL_UART_DISABLE_IT(huart, UART_IT_TC);
huart->gState = HAL_UART_STATE_READY;
HAL_UART_TxCpltCallback;//回调函数
我想这应该是库开发人员为了更加灵活方便,专门这样做的哦。
我现在手头没得环境,不然我就验证下

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版