OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4054|回复: 5

STM32CubeMX Hal库的一些坑

[复制链接]

1

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2014-11-17
在线时间
9 小时
发表于 2017-4-12 10:20:54 | 显示全部楼层 |阅读模式
本帖最后由 世上最美丽的裤头 于 2017-4-13 11:24 编辑

使用的是stm32f103 V1.40版本的库
UART DMA发送的问题
发送函数
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
发送完毕之后成功的回调函数也正常,可是再次发送的时候就发不出去了。一直返回错误。
我们看下这个函数的代码

[mw_shl_code=applescript,true]HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  uint32_t *tmp;
  uint32_t tmp_state = 0;

  tmp_state = huart->State;
  if((tmp_state == HAL_UART_STATE_READY) || (tmp_state == HAL_UART_STATE_BUSY_RX))
  {
    if((pData == NULL ) || (Size == 0))
    {
      return HAL_ERROR;
    }

    /* Process Locked */
    __HAL_LOCK(huart);

    huart->pTxBuffPtr = pData;
    huart->TxXferSize = Size;
    huart->TxXferCount = Size;

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    /* Check if a receive process is ongoing or not */
    if(huart->State == HAL_UART_STATE_BUSY_RX)
    {
      huart->State = HAL_UART_STATE_BUSY_TX_RX;
    }
    else
    {
      huart->State = HAL_UART_STATE_BUSY_TX;
    }

    /* 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;

    /* 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);

    /* 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);

    /* Process Unlocked */
    __HAL_UNLOCK(huart);

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}[/mw_shl_code]
代码中可以看出,发送之前先判断状态标志,不是在发送状态才进行发送,这也正常。但是,发送一次之后,状态就被至为发送状态,发送完毕也没有清楚,这就导致了下次再发送,判断为忙,就发不出去了。我们看下他发送成功的处理部分。
[mw_shl_code=applescript,true]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);
  }[/mw_shl_code]
代码中可以看到,并没有清除发送的状态,这就导致了下次发送不成功的问题。
难道要自己发送之前清除一下状态,我想这应该不是库函数的本意。
我们对比看下接收成功是如何处理的
[mw_shl_code=applescript,true]static void UART_DMAReceiveCplt(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->RxXferCount = 0;

    /* Disable the DMA transfer for the receiver request by setting the DMAR bit
       in the UART CR3 register */
    CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);

    /* Check if a transmit process is ongoing or not */
    if(huart->State == HAL_UART_STATE_BUSY_TX_RX)
    {
      huart->State = HAL_UART_STATE_BUSY_TX;
    }
    else
    {
      huart->State = HAL_UART_STATE_READY;
    }
  }
  HAL_UART_RxCpltCallback(huart);
}[/mw_shl_code]
接收成功之后有正确清除状态标志,发送成功应该也是同样的,所以可能是漏掉了。我们加上即可
[mw_shl_code=applescript,true]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);

      /* 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;
    }
  }
  /* DMA Circular mode */
  else     //普通模式没有回调发送成功,注释掉次else则修改为发送完成回调
  {
    HAL_UART_TxCpltCallback(huart);
  }
}[/mw_shl_code]

测试,可以正常发送了····

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2014-11-17
在线时间
9 小时
 楼主| 发表于 2017-4-12 10:21:51 | 显示全部楼层
先写的博客,怎么复制过来成这样了·········
回复 支持 反对

使用道具 举报

1

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1183
金钱
1183
注册时间
2015-5-28
在线时间
149 小时
发表于 2017-4-12 13:14:42 | 显示全部楼层
世上最美丽的裤头 发表于 2017-4-12 10:21
先写的博客,怎么复制过来成这样了·········

我喜欢你的ID~
回复 支持 反对

使用道具 举报

8

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
188
金钱
188
注册时间
2016-9-27
在线时间
28 小时
发表于 2017-4-12 13:44:00 | 显示全部楼层
楼主可以把你加的代码标记出来吗,怎么看了半天,也看到你加的是哪句
回复 支持 反对

使用道具 举报

8

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
188
金钱
188
注册时间
2016-9-27
在线时间
28 小时
发表于 2017-4-12 13:44:41 | 显示全部楼层
没看到你加的是哪句
回复 支持 反对

使用道具 举报

1

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2014-11-17
在线时间
9 小时
 楼主| 发表于 2017-4-13 11:25:19 | 显示全部楼层
gaoshanxiaolu 发表于 2017-4-12 13:44
没看到你加的是哪句

标记出来了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-8-22 09:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表