OpenEdv-开源电子网

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

关于USART的发送使用DMA中断

[复制链接]

19

主题

39

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
428
金钱
428
注册时间
2013-8-18
在线时间
40 小时
发表于 2017-8-24 17:14:04 | 显示全部楼层 |阅读模式
10金钱
求助:我目前调试STM32F429遇到这么一个问题。我的串口接收还是使用串口的接收中断,发送使用DMA发送。
但是DMA发送使能后,只进一次中断,之后就没有进入了。中断一直卡在串口2里面。

代码:
void USART2_Configuration(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  /*##-1- Enable peripherals Clocks ---------------------------------------*/
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_USART2_CLK_ENABLE();
  __HAL_RCC_DMA1_CLK_ENABLE();

  /*##-2- Configure peripheral GPIO ---------------------------------------*/
  /* UART TX GPIO pin configuration  */
  GPIO_InitStructure.Pin       = GPIO_PIN_3;
  GPIO_InitStructure.Mode      = GPIO_MODE_AF_PP;
  GPIO_InitStructure.Pull      = GPIO_PULLUP;
  GPIO_InitStructure.Speed     = GPIO_SPEED_FAST;
  GPIO_InitStructure.Alternate = GPIO_AF7_USART2;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* UART RX GPIO pin configuration  */
  GPIO_InitStructure.Pin       = GPIO_PIN_5;
  GPIO_InitStructure.Alternate = GPIO_AF7_USART2;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);

  /* USARTx configuration -------------------------------------------------*/
  USART2_Handle.Instance          = USART2;
  USART2_Handle.Init.BaudRate     = 256000;
  USART2_Handle.Init.WordLength   = UART_WORDLENGTH_8B;
  USART2_Handle.Init.StopBits     = UART_STOPBITS_1;
  USART2_Handle.Init.Parity       = UART_PARITY_NONE;
  USART2_Handle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
  USART2_Handle.Init.Mode         = UART_MODE_TX_RX;
  USART2_Handle.Init.OverSampling = UART_OVERSAMPLING_8;
  HAL_UART_Init(&USART2_Handle);

  /*##-3- Configure the DMA streams ##########################################*/
  /* Configure the DMA handler for Transmission process */
  USART2_DMA_TX_Handle.Instance                      = DMA1_Stream6;
  USART2_DMA_TX_Handle.Init.Channel                  = DMA_CHANNEL_4;
  USART2_DMA_TX_Handle.Init.Direction                 = DMA_MEMORY_TO_PERIPH;
  USART2_DMA_TX_Handle.Init.PeriphInc                = DMA_PINC_DISABLE;
  USART2_DMA_TX_Handle.Init.MemInc                 = DMA_MINC_ENABLE;
  USART2_DMA_TX_Handle.Init.PeriphDataAlignment  = DMA_PDATAALIGN_BYTE;
  USART2_DMA_TX_Handle.Init.MemDataAlignment   = DMA_MDATAALIGN_BYTE;
  USART2_DMA_TX_Handle.Init.Mode                     = DMA_NORMAL;
  USART2_DMA_TX_Handle.Init.Priority                   = DMA_PRIORITY_HIGH;
  USART2_DMA_TX_Handle.Init.FIFOMode             = DMA_FIFOMODE_DISABLE;
  USART2_DMA_TX_Handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
  USART2_DMA_TX_Handle.Init.MemBurst              = DMA_MBURST_SINGLE;
  USART2_DMA_TX_Handle.Init.PeriphBurst            = DMA_MBURST_SINGLE;
  HAL_DMA_Init(&USART2_DMA_TX_Handle);
  /* Associate the initialized DMA handle to the UART handle */
  __HAL_LINKDMA(&USART2_Handle, hdmatx, USART2_DMA_TX_Handle);

  __HAL_UART_ENABLE_IT(&USART2_Handle,UART_IT_RXNE);
}


中断函数是这个
void DMA1_Stream6_IRQHandler(void)
{
  HAL_DMA_IRQHandler(USART2_Handle.hdmatx);
}



使用这个发送数据
HAL_UART_Transmit_DMA(&USART2_Handle, (unsigned char*)DMA_Send_Buff, j);

也自己重新写了这个函数,但是不会进入。
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  if(huart->Instance == USART2)
  {
    __HAL_DMA_DISABLE(huart->hdmatx);
    USART_DMA_Send_Flag = 0;
  }
}


求有用过串口DMA发送的大神指教。究竟是什么地方出错了。










最佳答案

查看完整内容[请看2#楼]

这里面的串口中断需要使用HAL_UART_IRQHandler()这个函数才可以,原因是 DMA中断中调用了UART_DMATransmitCplt()函数,又因为DMA选择了NORMAL模式。所以它使能了USART_CR1_TCIE这一中断。导致进入了串口2一直卡死。 解决方式:在串口中断函数中使用HAL_UART_IRQHandler函数,或者使用 这个: /* DMA transfer complete */ if((0x00000040 & USART2->CR1) != 0 && (0x00000040 & USART2->SR) != 0) { /* Disable the ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

19

主题

39

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
428
金钱
428
注册时间
2013-8-18
在线时间
40 小时
 楼主| 发表于 2017-8-24 17:14:05 | 显示全部楼层
本帖最后由 chonchie 于 2017-8-25 11:31 编辑

这里面的串口中断需要使用HAL_UART_IRQHandler()这个函数才可以,原因是
DMA中断中调用了UART_DMATransmitCplt()函数,又因为DMA选择了NORMAL模式。所以它使能了USART_CR1_TCIE这一中断。导致进入了串口2一直卡死。
解决方式:在串口中断函数中使用HAL_UART_IRQHandler函数,或者使用
这个:
/* DMA transfer complete */
  if((0x00000040 & USART2->CR1) != 0 && (0x00000040 & USART2->SR) != 0)
  {
    /* Disable the UART Transmit Complete Interrupt */
    CLEAR_BIT(USART2_Handle.Instance->CR1, USART_CR1_TCIE);
    /* Tx process is ended, restore huart->gState to Ready */
    USART2_Handle.gState = HAL_UART_STATE_READY;
    /* disable DMA sending */
    __HAL_DMA_DISABLE(USART2_Handle.hdmatx);
  }
这个中断是需要自己清的。

以前的stdlib只需要在DMA里面操作清flag就可以了,现在的HAL库完成一个功能,需要跑两个中断才能完成。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165508
金钱
165508
注册时间
2010-12-1
在线时间
2115 小时
发表于 2017-8-25 01:09:32 | 显示全部楼层
帮顶
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-18 05:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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