stm32f103芯片的串口一直使用DMA+空闲中断,现在使用stm32h7芯片,打算也使用相同的方法 
芯片型号:stm32h743 
串口:USART2 
代码生成:stm32CubeMX 
第一步:使用stm32CubeMX生成代码 
 
第二步:添加自己代码 
 
1.发生空闲中断需要reset DMA重新开始接收数据 
 
- HAL_StatusTypeDef HAL_UART_DMAStopRx(UART_HandleTypeDef *huart)
 
 - {
 
 -   /* Stop UART DMA Rx request if ongoing */
 
 -   if ((huart->RxState == HAL_UART_STATE_BUSY_RX) &&
 
 -       (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)))
 
 -   {
 
 -     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);
 
 -     /* 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);
 
  
-         /* At end of Rx process, restore huart->RxState to Ready */
 
 -         huart->RxState = HAL_UART_STATE_READY;
 
 -   }
 
  
-   return HAL_OK;
 
 - }
 
 
  复制代码 
串口空闲中断 
 
- /**
 
 -   * @brief This function handles UART4 global interrupt.
 
 -   */
 
 - void USART2_IRQHandler(void)
 
 - {
 
 -         uint32_t _len_dmarev;
 
 -         uint32_t isrflags;
 
 -         uint32_t cr1its;
 
 -         BaseType_t xHigherPriorityTaskWoken;
 
  
-         
 
 -         HAL_UART_IRQHandler(&UART2_Handler);
 
  
-         isrflags   = READ_REG(UART2_Handler.Instance->ISR);
 
 -         cr1its     = READ_REG(UART2_Handler.Instance->CR1);
 
  
-         if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))
 
 -         {
 
 -                 __HAL_UART_CLEAR_IDLEFLAG(&UART2_Handler);
 
  
-                 _len_dmarev = DMA_BUFFER_LENGTH -                                         __HAL_DMA_GET_COUNTER(UART2_Handler.hdmarx);
 
  
-                 if(_len_dmarev)
 
 -                 {
 
 -                   //停止DMA
 
 -                   HAL_UART_DMAStopRx(&UART2_Handler);
 
 -                 //这个地方非常关键,DMA访问的ram,但是CPU访问的是cache,使用下面函数使ram和cache一致
 
 -                  SCB_InvalidateDCache_by_Addr((uint32_t *)dma_rx_buf, DMA_BUFFER_LENGTH);
 
 -                  
 
 -                  xQueueSendToBackFromISR(Keyboard_Queue,(void*)&uart_to_keyboard_msg,&xHigherPriorityTaskWoken);
 
 -                  
 
 -                  portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
 
  
-                   HAL_UART_Receive_DMA(&UART2_Handler, dma_rx_buf, DMA_BUFFER_LENGTH);
 
 -                   __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_ERR);
 
 -                   __HAL_UART_DISABLE_IT(&UART2_Handler, UART_IT_PE);
 
 -                 }
 
 -           else
 
 -           {
 
 -                   READ_REG(UART2_Handler.Instance->RDR);
 
 -                   __HAL_UART_CLEAR_OREFLAG(&UART2_Handler);
 
 -           }
 
  
-   }
 
  
- }
 
 
  复制代码 
发送函数 
 
- unsigned int KeyboardRs485TxFrame(uint8_t * buffer,uint32_t len)
 
 - {
 
 - UINT16 i;
 
  
- //拷贝数据到DMA buffer
 
 - for(i = 0; i < len; i++)
 
 - {
 
 -         dma_tx_buf<i> =</i> buffer; 
 
 - }
 
  
- //使发送RAM和cache一致
 
 - SCB_InvalidateDCache_by_Addr((uint32_t *)dma_tx_buf, DMA_BUFFER_LENGTH);
 
 - HAL_UART_Transmit_DMA(&UART2_Handler, dma_tx_buf, len);
 
 - return 0;
 
  复制代码 
还有一点需要特别注意:DMA访问的是0x24000000以后区域,定义的发送和接收DMA buffer 一定要在这个区域 
可使用下面的编译指令: 
- ALIGN_32BYTES(attribute((section (".RAM_D2"))) uint8_t dma_rx_buf[DMA_BUFFER_LENGTH]) ;
 
 - ALIGN_32BYTES(attribute((section (".RAM_D2"))) uint8_t dma_tx_buf[DMA_BUFFER_LENGTH]);
 
 
  复制代码 
 |