×
单片机 > 单片机程序设计 > 详情

STM32CubeMX Hal库的一些坑

发布时间:2020-06-16 发布时间:
|

使用的是stm32f103 V1.40版本的库


UART DMA发送的问题


发送函数 

HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); 

发送完毕之后成功的回调函数也正常,可是再次发送的时候就发不出去了。一直返回错误。 

我们看下这个函数的代码


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;

  }

}


代码中可以看出,发送之前先判断状态标志,不是在发送状态才进行发送,这也正常。但是,发送一次之后,状态就被至为发送状态,发送完毕也没有清楚,这就导致了下次再发送,判断为忙,就发不出去了。我们看下他发送成功的处理部分。


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

  }

}


代码中可以看到,并没有清除发送的状态,这就导致了下次发送不成功的问题。 

难道要自己发送之前清除一下状态,我想这应该不是库函数的本意。 

我们对比看下接收成功是如何处理的


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

}


接收成功之后有正确清除状态标志,发送成功应该也是同样的,所以可能是漏掉了。我们加上即可


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

  {

    HAL_UART_TxCpltCallback(huart);

  }

}


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


Flash读写保护


HAL的库flash对比标准库变化还是挺大的,写保护这块需要手动去配置。 

上代码


FLASH_OBProgramInitTypeDef obProgram;


    __HAL_FLASH_PREFETCH_BUFFER_DISABLE();


    HAL_FLASHEx_OBGetConfig(&obProgram);


    if (obProgram.RDPLevel == OB_RDP_LEVEL_0)

    {

        obProgram.OptionType = OPTIONBYTE_WRP;  //读写保护

        obProgram.WRPState = OB_WRPSTATE_ENABLE;    //使能

        obProgram.WRPPage = OB_WRP_ALLPAGES;    //所有页

        obProgram.Banks = FLASH_BANK_1;         

        obProgram.RDPLevel = OB_RDP_LEVEL_1;


        HAL_FLASH_Unlock();

        HAL_FLASH_OB_Unlock();

        HAL_FLASHEx_OBProgram(&obProgram);

        HAL_FLASH_OB_Lock();

        HAL_FLASH_Lock();

    }

    __HAL_FLASH_PREFETCH_BUFFER_ENABLE();


关键字:STM32  CubeMX  Hal库 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
8051单片机的函数发生器的设计