stm32cubemx生成HAL库的串口DMA使用问题

今天使用串口DMA做收发数据,在使用DMA接收数据的过程中,有一些关于HAL库的使用问题,和大家讨论分享一下。

下面是关于串口的配置,就不贴所有配置了。大家关注重点哈。

关于串口DMA配置:

首先说第一个问题,在使用stm32cubemx生成HAL库代码时,偶尔会出现SystemClock_Config();重复被调用的情况,由于这部分代码是软件生成的,部分人可能注意不到有这样的问题,但这里第二次调用后会使程序进入error状态,问题出现的原因还不清楚,希望有大佬看见能给出原因和j解决办法哈。

uint8_t ping_str[256];

uint8_t pang_str[256];

uint8_t *rxdata = ping_str ;

首先在main函数中启动串口DMA,调用函数HAL_UART_Receive_DMA(&huart1,rxdata,256);
 

这里串口DMA通道为DMA1_Channel5。接收方式为乒乓接收,就是每次接收成功后重新调用HAL_UART_Receive_DMA(&huart1,rxdata,256);而rxdata指向的地址在ping_str和pang_str之间切换,解析数据也是在pingstr和pangstr之间相互解析,在调试过程中发现,每两次才能成功的接收一次数据,再次调试时发现只有开始时指向ping_str生效了,后面切换的pang_str没有生效,导致第二次解析pang_str数据时,数据内容为0。还有就是DMA1_Channel5->CNDTR在每次解析完成数据后,没有被重置。导致一直检测缓冲区中有数据,影响程序运行。

 

以上所有的问题,原因都是在二次调用HAL_UART_Receive_DMA(&huart1,rxdata,256);函数时,没有生效导致的。第一步是huart->RxState == HAL_UART_STATE_READY判断不通过导致失败,强行赋值huart1.RxState = HAL_UART_STATE_READY;后,通过判断。

通过判断后,其中HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t *)tmp, Size);也没有生效,问题在于__HAL_LOCK(hdma);不通过。这里也没有办法解决,同样希望有大佬指导。

虽然有以上的问题,但是我发现可以通过改造重写DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);实现DMA重新配置。

这是HAL库的源代码

/**
  * @brief  Sets the DMA Transfer parameter.
  * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
  *                     the configuration information for the specified DMA Channel.
  * @param  SrcAddress: The source memory Buffer address
  * @param  DstAddress: The destination memory Buffer address
  * @param  DataLength: The length of data to be transferred from source to destination
  * @retval HAL status
  */
static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
  /* Clear all flags */
  hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);

  /* Configure DMA Channel data length */
  hdma->Instance->CNDTR = DataLength;

  /* Memory to Peripheral */
  if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
  {
    /* Configure DMA Channel destination address */
    hdma->Instance->CPAR = DstAddress;

    /* Configure DMA Channel source address */
    hdma->Instance->CMAR = SrcAddress;
  }
  /* Peripheral to Memory */
  else
  {
    /* Configure DMA Channel source address */
    hdma->Instance->CPAR = SrcAddress;

    /* Configure DMA Channel destination address */
    hdma->Instance->CMAR = DstAddress;
  }
}

这是改造后的代码

void DMA1_SetConfig(uint8_t *pData, uint32_t DataLength)
{
	uint32_t *tmp = (uint32_t *)&pData;
	uint32_t DstAddress = *tmp;
	/* Clear all flags */
	huart1.hdmarx->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << huart1.hdmarx->ChannelIndex);

  /* Configure DMA Channel data length */
  DMA1_Channel5->CNDTR = DataLength;
	
  /* Configure DMA Channel source address */
  DMA1_Channel5->CPAR = (uint32_t)&USART1->DR;

  /* Configure DMA Channel destination address */
  DMA1_Channel5->CMAR = DstAddress;

}
DMA1_Channel5->CCR &= 0xFFFE;
DMA1_SetConfig((uint8_t*)SciaRxbufHandle->DATA.inbuff,256);
DMA1_Channel5->CCR |= 0x01;

通过调用以上代码,基本上实现乒乓接收。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值