菜鸟小小 发表于 2016-11-15 09:07:57

谢谢分享

haifeng-388081 发表于 2016-11-15 09:43:48

学习了,   

zbber 发表于 2016-11-15 10:09:59

你应该用DMA中断将数据移到缓冲区

秋水之下 发表于 2017-5-4 11:36:21

zbber 发表于 2016-11-15 10:09
你应该用DMA中断将数据移到缓冲区

就是啊,本来就应该这样处理呀

eker 发表于 2017-5-4 13:41:59

斜阳__ 发表于 2016-6-15 10:21
我刚做过用串口DMA接收不定长数据,使能空闲中断,在空闲中断触发的时候停止DMA,取出数据,之后使用HAL_UA ...

哥,请问你怎么做的,能给段代码看看吗

斜阳__ 发表于 2017-5-8 14:11:34

打开DMA接收:HAL_UART_Receive_DMA(&guiSerial,guiRcvBuf,guiRcvBufLen);下面是中断处理;guiDataRcvCallBack是我自己定义的接收完成的回调                uint32_t temp;
                if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE)!=RESET)
                {
                        __HAL_UART_CLEAR_IDLEFLAG(&huart2);
                        temp = huart2.Instance->SR;
                        temp = huart2.Instance->DR;
                        HAL_UART_DMAStop(&huart2);
                        temp=hdma_usart2_rx.Instance->NDTR;
                        guiDataRcvCallBack(guiRcvBufLen-temp);
                }


whtt 发表于 2017-5-8 15:17:55

二楼说的很好,原因就是如此。其实在STM32官网公众号有文章介绍了该问题,主要是先启动了串口再启动DMA就会容易引起该问题。因此为了防止该问题要不每次开DMA都清ORE寄存器;要不按规矩先开DMA再开串口,不用了先关串口再关DMA

喜欢吃青椒麽 发表于 2018-1-26 11:35:28

斜阳__ 发表于 2016-6-15 10:21
我刚做过用串口DMA接收不定长数据,使能空闲中断,在空闲中断触发的时候停止DMA,取出数据,之后使用HAL_UA ...

正常方法是这样。
但是使用空闲中断也有一个问题,就是的发送端发送一帧数据不能被打断。不然stm32就会触发空闲中断,只接收到一帧的一部分数据。
空闲中断就是这个串口线有一个字节的时间没有数据传输就触发空闲中断吧。
那么假设我发送端要发送一帧数据,共20个字节,那么假设在发送到第10个字节的时候,被中断打断了,打断了之后恢复发送,那么打断到恢复发送这段时间超过了传输一个字节的时间,则就会触发接收端的空闲中断。
则接收端只接收到了10个字节,这个时候在中断里面关闭DMA再开启已经来不及接收后面的了?
这个问题怎么解决的阿?

龙吟风独恋云 发表于 2018-5-11 17:04:22

本帖最后由 龙吟风独恋云 于 2018-5-11 17:05 编辑

针对第2点,串口DMA接收不能单独停止。

HAL_UART_DMAStop()函数的确是uart接收和发送同时关闭,找了好久终于找到只关闭接收的函数了。
只关闭接收的函数。HAL_UART_AbortReceive()

下面看一下函数具体实现:
HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)
{
uint32_t dmarequest = 0x00U;
/* The Lock is not implemented on this API to allow the user application
   to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback():
   when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
   and the correspond call back is executed HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback()
   */
/* Stop UART DMA Tx request if ongoing */
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT);
if((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest)
{
    CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
    /* Abort the UART DMA Tx channel */
    if(huart->hdmatx != NULL)
    {
      HAL_DMA_Abort(huart->hdmatx);
    }
    UART_EndTxTransfer(huart);
}
/* Stop UART DMA Rx request if ongoing */
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
if((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest)
{
    CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
    /* Abort the UART DMA Rx channel */
    if(huart->hdmarx != NULL)
    {
      HAL_DMA_Abort(huart->hdmarx);
    }
    UART_EndRxTransfer(huart);
}
return HAL_OK;
}

主要分为2大部分,处理标志,关闭发送和接收DMA。

HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart)
{
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* Disable the UART DMA Rx request if enabled */
if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
{
    CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
    /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */
    if(huart->hdmarx != NULL)
    {
      /* Set the UART DMA Abort callback to Null.
         No call back execution at end of DMA abort procedure */
      huart->hdmarx->XferAbortCallback = NULL;
      HAL_DMA_Abort(huart->hdmarx);
    }
}
/* Reset Rx transfer counter */
huart->RxXferCount = 0x00U;
/* Restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
return HAL_OK;
}

也是分为2部分,处理标志和关闭接收DMA。

最简单的实现:
1. 先关闭接收DMA,HAL_DMA_Abort(huart->hdmarx);
2. 置位RX ready状态,huart->RxState = HAL_UART_STATE_READY;
忽略了错误标志和IT标志处理,最保险的方式还是使用HAL_UART_AbortReceive()函数。

any012 发表于 2018-11-23 11:30:07

任风吹吹 发表于 2016-6-15 11:28
当你将接收DMA关闭后,此时串口还是激活的,若此时串口来数据,无法触发DMA传输,此时产生上溢错误(ORE) ...

正好遇到了这个问题。
群里朋友帮找到了这个帖子,收益匪浅。
页: 1 [2] 3
查看完整版本: HAL库的串口DMA操作方法很难理解,非常的不好用