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

uart dma接收问题

[复制链接]
312011 提问时间:2018-6-13 20:13 /
HAL_UART_Receive_DMA能在中断处理函数里使用吗?
收藏 1 评论9 发布时间:2018-6-13 20:13

举报

9个回答
电子星辰 回答时间:2018-6-13 20:40:50
应该是没问题的,别在串口中断里用就好

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

312011 回答时间:2018-6-14 06:49:00
谢谢,我本来想在接收空闲中断处理函数里使用它接收数据
电子星辰 回答时间:2018-6-14 13:29:39
312011 发表于 2018-6-14 06:49
谢谢,我本来想在接收空闲中断处理函数里使用它接收数据

哦,DMA+配合空闲中断我没用过,但是很多人都这么用,在空闲中断里开关DMA接收应该是可以的
switcc 回答时间:2018-6-14 15:51:01
空闲中断里首先abort dma,然后再启动就能实现不定长串口接收

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

312011 回答时间:2018-6-14 20:04:26
今天调了一天,还没搞定,情况是有时候发一次收不到,得发两次甚至更多次才能收到,明天把代码贴出来,各位帮忙给看看。另外f7的串口dma接收例子,上面说明最多接收10个字节,没说必须接收10个字节,明天用f7的开发版验证一下,另外再看看f7的历程有没有开空闲中断
312011 回答时间:2018-6-15 13:11:14
今天试了F769的开发板,一样usart DMA接收只能接收固定长度。
我的程序代码,哪位帮忙看看,谢谢!
有的时候要发送两次甚至更多次才能接收,第一次多的NDRT数值为0,串口调试助手再发送一次,才能接收到.
/*
* uart1 dma rx idle intrrupt process
*/
void Addedto_USART1_IRQHandler(void)
{
        if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET) //uart1 dma rx idle intrrupt
        {
                static  uint32_t rxdatanum,temp;
        
                __HAL_UART_CLEAR_IDLEFLAG(&huart1);        //clear uart1 dma rx idle intrrupt flag
                temp =huart1.Instance->SR;
                temp =huart1.Instance->DR;
                temp=huart1.hdmarx->Instance->NDTR;
//                CLEAR_BIT(huart1.Instance->CR3, USART_CR3_DMAR);
//                HAL_DMA_Abort(huart1.hdmarx);
                __HAL_DMA_DISABLE(huart1.hdmarx);
                rxdatanum=UART_DMA_RX_SIZE-(__HAL_DMA_GET_COUNTER(huart1.hdmarx));
               
                /* Enable the DMA transfer for the receiver request by setting the DMAR bit
    in the UART CR3 register */
    SET_BIT(huart1.Instance->CR3, USART_CR3_DMAR);
                /* Enable the Peripheral */
    __HAL_DMA_ENABLE(huart1.hdmarx);
               
                osMessagePut(Queue_EventUart,(rxdatanum +((uint32_t )EVENT_UART1_RX<<16)),0);//send rx event
        }        
        
}

/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
        
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
        Addedto_USART1_IRQHandler();
  /* USER CODE END USART1_IRQn 1 */
}
为什么这样第一次无法正确接收,需要发两次甚至更多次才能收到上一次的数据?中断停在这个空闲中断处理函数里的sMessagePut函数,发现rxdatanum和temp值不正确,什么原因?
switcc 回答时间:2018-6-19 10:23:49
本帖最后由 Switcc 于 2018-6-19 10:29 编辑

这是我在H7上面用的空闲中断+DMA,给你参考一下:

/**********初始化串口4***********/
void MX_UART4_Init(void)
{

  huart4.Instance = UART4;
  huart4.Init.BaudRate = 115200;
  huart4.Init.WordLength=UART_WORDLENGTH_8B;
  huart4.Init.StopBits = UART_STOPBITS_1;
  huart4.Init.Parity = UART_PARITY_NONE;
  huart4.Init.Mode = UART_MODE_TX_RX;
  huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart4.Init.OverSampling = UART_OVERSAMPLING_16;
  huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart4.Init.Prescaler = UART_PRESCALER_DIV1;
  huart4.Init.FIFOMode = UART_FIFOMODE_DISABLE;
  huart4.Init.TXFIFOThreshold = UART_TXFIFO_THRESHOLD_1_8;
  huart4.Init.RXFIFOThreshold = UART_RXFIFO_THRESHOLD_1_8;
  huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
   __HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);//使能空闲中断
        HAL_UART_Receive_DMA(&huart4, (uint8_t*)uart4Rx,UART_RECEIVE_MAX);//启动DMA接收65535个字节
}



/************DMA配置*************/
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(uartHandle->Instance==UART4)
  {
  /* USER CODE BEGIN UART4_MspInit 0 */

  /* USER CODE END UART4_MspInit 0 */
    /* UART4 clock enable */
    __HAL_RCC_UART4_CLK_ENABLE();
  
    /**UART4 GPIO Configuration   
    PC10     ------> UART4_TX
    PC11     ------> UART4_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    /* UART4 DMA Init */
    /* UART4_RX Init */
    hdma_uart4_rx.Instance = DMA1_Stream4;
    hdma_uart4_rx.Init.Request = DMA_REQUEST_UART4_RX;
    hdma_uart4_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_uart4_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart4_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart4_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart4_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart4_rx.Init.Mode = DMA_CIRCULAR;//配置成normal也可以,随便
    hdma_uart4_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_uart4_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_uart4_rx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_uart4_rx);

    /* UART4_TX Init */
    hdma_uart4_tx.Instance = DMA1_Stream5;
    hdma_uart4_tx.Init.Request = DMA_REQUEST_UART4_TX;
    hdma_uart4_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_uart4_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart4_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart4_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart4_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart4_tx.Init.Mode = DMA_NORMAL;
    hdma_uart4_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_uart4_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_uart4_tx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(uartHandle,hdmatx,hdma_uart4_tx);

    /* UART4 interrupt Init */
    HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(UART4_IRQn);
  /* USER CODE BEGIN UART4_MspInit 1 */

  /* USER CODE END UART4_MspInit 1 */
  }
}

/**
* @brief This function handles UART4 global interrupt.
*/
/**********串口4中断入口***********/
void UART4_IRQHandler(void)
{
  /* USER CODE BEGIN UART4_IRQn 0 */

  /* USER CODE END UART4_IRQn 0 */
  HAL_UART_IRQHandler(&huart4);
  /* USER CODE BEGIN UART4_IRQn 1 */
if(__HAL_UART_GET_FLAG(&huart4,UART_FLAG_IDLE)!=RESET)//判断是否是空闲中断
        {
                __HAL_UART_CLEAR_IDLEFLAG(&huart4);
                uart_rx_idle_callback(&huart4);
        }
  /* USER CODE END UART4_IRQn 1 */
}


/**************空闲中断处理***************/
void uart_rx_idle_callback(UART_HandleTypeDef *huart)
{
        uint32_t temp;
        if(huart->Instance==USART6)
        {
                uint32_t len;
                HAL_UART_DMAStop(&huart6);
                temp=((DMA_Stream_TypeDef   *)hdma_usart6_rx.Instance)->NDTR;
                //printf("%d\r\n",UART_RECEIVE_MAX-temp);
                uart6RxLen=UART_RECEIVE_MAX-temp;
                HAL_UART_Receive_DMA(&huart6, (uint8_t*)uart6Rx,UART_RECEIVE_MAX);
        }
        else if(huart->Instance==UART4)
        {
                HAL_UART_DMAStop(&huart4);
                temp=((DMA_Stream_TypeDef   *)hdma_uart4_rx.Instance)->NDTR;
                //printf("%d\r\n",UART_RECEIVE_MAX-temp);
                uart4RxLen=UART_RECEIVE_MAX-temp;//实际接收长度,必须小于65535

                 /**********/
                HAL_UART_Receive_DMA(&huart4, (uint8_t*)uart4Rx,UART_RECEIVE_MAX);//再次启动DMA接收
        }
}



评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

McDong 回答时间:2018-8-3 16:20:33
正在做此类应用,很感谢大家的分享,受益匪浅,让新手少走好多弯路
ciipeter 回答时间:2019-6-26 22:34:45
312011 发表于 2018-6-15 13:11
今天试了F769的开发板,一样usart DMA接收只能接收固定长度。
我的程序代码,哪位帮忙看看,谢谢!
有的时 ...

你好,你这个问题解决了吗,我先也碰到这个问题了,两天了还没解决,求指教

所属标签

相似问题

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