• STM32 HAL 用DMA+空闲中断接收不定长数据


    1. static uint8_t Rxd1Data[512];
    2. static uint16_t Tx_length;
    1. void MX_USART1_UART_Init(void)
    2. {
    3. /* USER CODE BEGIN USART1_Init 0 */
    4. /* USER CODE END USART1_Init 0 */
    5. /* USER CODE BEGIN USART1_Init 1 */
    6. /* USER CODE END USART1_Init 1 */
    7. huart1.Instance = USART1;
    8. huart1.Init.BaudRate = 115200;
    9. huart1.Init.WordLength = UART_WORDLENGTH_8B;
    10. huart1.Init.StopBits = UART_STOPBITS_1;
    11. huart1.Init.Parity = UART_PARITY_NONE;
    12. huart1.Init.Mode = UART_MODE_TX_RX;
    13. huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    14. huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    15. if (HAL_UART_Init(&huart1) != HAL_OK)
    16. {
    17. Error_Handler();
    18. }
    19. /* USER CODE BEGIN USART1_Init 2 */
    20. /* USER CODE END USART1_Init 2 */
    21. }
    1. void MX_USART2_UART_Init(void)
    2. {
    3. /* USER CODE BEGIN USART2_Init 0 */
    4. /* USER CODE END USART2_Init 0 */
    5. /* USER CODE BEGIN USART2_Init 1 */
    6. /* USER CODE END USART2_Init 1 */
    7. huart2.Instance = USART2;
    8. huart2.Init.BaudRate = 115200;
    9. huart2.Init.WordLength = UART_WORDLENGTH_8B;
    10. huart2.Init.StopBits = UART_STOPBITS_1;
    11. huart2.Init.Parity = UART_PARITY_NONE;
    12. huart2.Init.Mode = UART_MODE_TX_RX;
    13. huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    14. huart2.Init.OverSampling = UART_OVERSAMPLING_16;
    15. if (HAL_UART_Init(&huart2) != HAL_OK)
    16. {
    17. Error_Handler();
    18. }
    19. /* USER CODE BEGIN USART2_Init 2 */
    20. /* USER CODE END USART2_Init 2 */
    21. }
    1. if(uartHandle->Instance==USART1)
    2. {
    3. /* USER CODE BEGIN USART1_MspInit 0 */
    4. /* USER CODE END USART1_MspInit 0 */
    5. /* USART1 clock enable */
    6. __HAL_RCC_USART1_CLK_ENABLE();
    7. __HAL_RCC_GPIOA_CLK_ENABLE();
    8. /**USART1 GPIO Configuration
    9. PA9 ------> USART1_TX
    10. PA10 ------> USART1_RX
    11. */
    12. GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    13. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    14. GPIO_InitStruct.Pull = GPIO_NOPULL;
    15. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    16. GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    17. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    18. /* USART1 DMA Init */
    19. /* USART1_TX Init */
    20. hdma_usart1_tx.Instance = DMA2_Stream7;
    21. hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;
    22. hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    23. hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    24. hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
    25. hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    26. hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    27. hdma_usart1_tx.Init.Mode = DMA_NORMAL;
    28. hdma_usart1_tx.Init.Priority = DMA_PRIORITY_HIGH;
    29. hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    30. if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
    31. {
    32. Error_Handler();
    33. }
    34. __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);
    35. /* USART1_RX Init */
    36. hdma_usart1_rx.Instance = DMA2_Stream2;
    37. hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
    38. hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    39. hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    40. hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    41. hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    42. hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    43. hdma_usart1_rx.Init.Mode = DMA_NORMAL;
    44. hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    45. hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    46. if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    47. {
    48. Error_Handler();
    49. }
    50. __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);
    51. /* USART1 interrupt Init */
    52. HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
    53. HAL_NVIC_EnableIRQ(USART1_IRQn);
    54. /* USER CODE BEGIN USART1_MspInit 1 */
    55. UART_Start_Receive_DMA(&huart1, Rxd1Data, 512);
    56. __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
    57. /* USER CODE END USART1_MspInit 1 */
    58. }
    59. else if(uartHandle->Instance==USART2)
    60. {
    61. /* USER CODE BEGIN USART2_MspInit 0 */
    62. /* USER CODE END USART2_MspInit 0 */
    63. /* USART2 clock enable */
    64. __HAL_RCC_USART2_CLK_ENABLE();
    65. __HAL_RCC_GPIOD_CLK_ENABLE();
    66. /**USART2 GPIO Configuration
    67. PD5 ------> USART2_TX
    68. PD6 ------> USART2_RX
    69. */
    70. GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
    71. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    72. GPIO_InitStruct.Pull = GPIO_NOPULL;
    73. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    74. GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    75. HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    76. /* USART2 DMA Init */
    77. /* USART2_RX Init */
    78. hdma_usart2_rx.Instance = DMA1_Stream5;
    79. hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4;
    80. hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    81. hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    82. hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
    83. hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    84. hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    85. hdma_usart2_rx.Init.Mode = DMA_NORMAL;
    86. hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;
    87. hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    88. if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
    89. {
    90. Error_Handler();
    91. }
    92. __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx);
    93. /* USART2_TX Init */
    94. hdma_usart2_tx.Instance = DMA1_Stream6;
    95. hdma_usart2_tx.Init.Channel = DMA_CHANNEL_4;
    96. hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    97. hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    98. hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
    99. hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    100. hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    101. hdma_usart2_tx.Init.Mode = DMA_NORMAL;
    102. hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
    103. hdma_usart2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    104. if (HAL_DMA_Init(&hdma_usart2_tx) != HAL_OK)
    105. {
    106. Error_Handler();
    107. }
    108. __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart2_tx);
    109. /* USART2 interrupt Init */
    110. HAL_NVIC_SetPriority(USART2_IRQn, 5, 0);
    111. HAL_NVIC_EnableIRQ(USART2_IRQn);
    112. /* USER CODE BEGIN USART2_MspInit 1 */
    113. /* USER CODE END USART2_MspInit 1 */
    114. }

    这里的 这二行比较关键, 

    第一:是禁止DMA 这里才能设置DNTR. 

    第二:还必须等待设置成功  里面有这么一句

     while((hdma->Instance->CR & DMA_SxCR_EN) != RESET){};

    /* Clear all interrupt flags at correct offset within the register */
        regs->IFCR = 0x3FU << hdma->StreamIndex;

    如果不要HAL_DMA_Abort(),测试发现  发二帧,第一帧会收不到,第二帧可以。

                HAL_DMA_Abort(huart->hdmarx);  //__HAL_DMA_DISABLE(huart->hdmarx);

                __HAL_DMA_SET_COUNTER(huart->hdmarx, 512);  

    下面实现一个UART1接收  UART2 转发出去。

    1. void HAL_UART_RxIdleCallback(UART_HandleTypeDef *huart)
    2. {
    3. if (huart->Instance == USART1)
    4. {
    5. if (huart->ErrorCode == HAL_UART_ERROR_NONE)
    6. {
    7. Tx_length = 512 - __HAL_DMA_GET_COUNTER(huart->hdmarx);
    8. HAL_UART_Transmit_DMA(&huart2, Rxd1Data, Tx_length);
    9. //__HAL_DMA_DISABLE(huart->hdmarx);
    10. HAL_DMA_Abort(huart->hdmarx);
    11. __HAL_DMA_SET_COUNTER(huart->hdmarx, 512);
    12. UART_Start_Receive_DMA(huart, Rxd1Data, 512);
    13. }
    14. }
    15. }

     

  • 相关阅读:
    算法与数据结构 --- 栈的表示和操作的实现
    CommonAPI SomeIP Runtime 交叉编译
    YoloV8改进策略:Inner-IoU+clou,YoloV8的涨点明珠
    一分钟学习数据安全—自主管理身份SSI可验证凭证
    MybatisPlus
    Eureka的Ribbon负载均衡
    Flex 布局项目实战,好像没那么难!
    RTU远程终端控制系统S274
    SQL行列转换
    企业IP地址管理(IPAM)
  • 原文地址:https://blog.csdn.net/eydj2008/article/details/125556296