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

【经验分享】STM32H7串口DMA+空闲中断实现接收和发送不定长度数据

[复制链接]
STMCU小助手 发布时间:2021-12-27 21:00
stm32f103芯片的串口一直使用DMA+空闲中断,现在使用stm32h7芯片,打算也使用相同的方法
芯片型号:stm32h743
串口:USART2
代码生成:stm32CubeMX
第一步:使用stm32CubeMX生成代码

第二步:添加自己代码

1.发生空闲中断需要reset DMA重新开始接收数据

  1. HAL_StatusTypeDef HAL_UART_DMAStopRx(UART_HandleTypeDef *huart)
  2. {
  3.   /* Stop UART DMA Rx request if ongoing */
  4.   if ((huart->RxState == HAL_UART_STATE_BUSY_RX) &&
  5.       (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)))
  6.   {
  7.     CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);

  8.     /* Abort the UART DMA Rx channel */
  9.     if(huart->hdmarx != NULL)
  10.     {
  11.       HAL_DMA_Abort(huart->hdmarx);
  12.     }

  13.     //UART_EndRxTransfer(huart);
  14.     /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
  15.         CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
  16.         CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);

  17.         /* At end of Rx process, restore huart->RxState to Ready */
  18.         huart->RxState = HAL_UART_STATE_READY;
  19.   }

  20.   return HAL_OK;
  21. }
复制代码

串口空闲中断

  1. /**
  2.   * @brief This function handles UART4 global interrupt.
  3.   */
  4. void USART2_IRQHandler(void)
  5. {
  6.         uint32_t _len_dmarev;
  7.         uint32_t isrflags;
  8.         uint32_t cr1its;
  9.         BaseType_t xHigherPriorityTaskWoken;

  10.         
  11.         HAL_UART_IRQHandler(&UART2_Handler);

  12.         isrflags   = READ_REG(UART2_Handler.Instance->ISR);
  13.         cr1its     = READ_REG(UART2_Handler.Instance->CR1);

  14.         if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))
  15.         {
  16.                 __HAL_UART_CLEAR_IDLEFLAG(&UART2_Handler);

  17.                 _len_dmarev = DMA_BUFFER_LENGTH -                                         __HAL_DMA_GET_COUNTER(UART2_Handler.hdmarx);

  18.                 if(_len_dmarev)
  19.                 {
  20.                   //停止DMA
  21.                   HAL_UART_DMAStopRx(&UART2_Handler);
  22.                 //这个地方非常关键,DMA访问的ram,但是CPU访问的是cache,使用下面函数使ram和cache一致
  23.                  SCB_InvalidateDCache_by_Addr((uint32_t *)dma_rx_buf, DMA_BUFFER_LENGTH);
  24.                  
  25.                  xQueueSendToBackFromISR(Keyboard_Queue,(void*)&uart_to_keyboard_msg,&xHigherPriorityTaskWoken);
  26.                  
  27.                  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

  28.                   HAL_UART_Receive_DMA(&UART2_Handler, dma_rx_buf, DMA_BUFFER_LENGTH);
  29.                   __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_ERR);
  30.                   __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_PE);
  31.                 }
  32.           else
  33.           {
  34.                   READ_REG(UART2_Handler.Instance->RDR);
  35.                   __HAL_UART_CLEAR_OREFLAG(&UART2_Handler);
  36.           }

  37.   }

  38. }
复制代码

发送函数

  1. unsigned int KeyboardRs485TxFrame(uint8_t * buffer,uint32_t len)
  2. {
  3. UINT16 i;

  4. //拷贝数据到DMA buffer
  5. for(i = 0; i < len; i++)
  6. {
  7.         dma_tx_buf<i> =</i> buffer;
  8. }

  9. //使发送RAM和cache一致
  10. SCB_InvalidateDCache_by_Addr((uint32_t *)dma_tx_buf, DMA_BUFFER_LENGTH);
  11. HAL_UART_Transmit_DMA(&UART2_Handler, dma_tx_buf, len);
  12. return 0;
复制代码

还有一点需要特别注意:DMA访问的是0x24000000以后区域,定义的发送和接收DMA buffer 一定要在这个区域
可使用下面的编译指令:
  1. ALIGN_32BYTES(attribute((section (".RAM_D2"))) uint8_t dma_rx_buf[DMA_BUFFER_LENGTH]) ;
  2. ALIGN_32BYTES(attribute((section (".RAM_D2"))) uint8_t dma_tx_buf[DMA_BUFFER_LENGTH]);
复制代码

收藏 评论0 发布时间:2021-12-27 21:00

举报

0个回答

所属标签

相似分享

官网相关资源

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