STM32
直播中

余温重顾

9年用户 918经验值
擅长:可编程逻辑 嵌入式技术 EMC/EMI设计
私信 关注
[问答]

STM32 HAL库使用IRDA串口IDLE+DMA发送失败的原因?

最近在把标准库的项目移植到HAL库中,同时使用freeRTOS进行任务管理,HAL库属于初学。
硬件:STM32F103RCT6+IRDA
简介:使用SMT32F103RCT6+IRDA模块作为上位机与STM32F103C8T6+IRDA下位机通过modbus通讯
软件:STM32CUBEIDE开发工具和生成的软件,freeRTOS

问题概要:正常运行时,收到命令A的回复,对回复进行解析后,再发送命令B,会出现命令发送失败的情况,但是单步调试时,发送可以成功,添加延时函数还是不行。

还请论坛各位同仁帮忙看看,提一下意见,谢谢

相关代码如下:

  • void HAL_IRDA_MspInit(IRDA_HandleTypeDef* irdaHandle)
  • {

  •   GPIO_InitTypeDef GPIO_InitStruct = {0};
  •   if(irdaHandle->Instance==USART1)
  •   {
  •   /* USER CODE BEGIN USART1_MspInit 0 */
  •   /* USER CODE END USART1_MspInit 0 */
  •     /* USART1 clock enable */
  •     __HAL_RCC_USART1_CLK_ENABLE();

  •     __HAL_RCC_GPIOA_CLK_ENABLE();
  •     /**USART1 GPIO Configuration
  •     PA9     ------> USART1_TX
  •     PA10     ------> USART1_RX
  •     */
  •     GPIO_InitStruct.Pin = GPIO_PIN_9;
  •     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  •     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  •     HAL_GPIO_Init(GPIOA,  GPIO_InitStruct);

  •     GPIO_InitStruct.Pin = GPIO_PIN_10;
  •     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  •     GPIO_InitStruct.Pull = GPIO_NOPULL;
  •     HAL_GPIO_Init(GPIOA,  GPIO_InitStruct);

  •     /* USART1 DMA Init */
  •     /* USART1_RX Init */
  •     hdma_usart1_rx.Instance = DMA1_Channel5;
  •     hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
  •     hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
  •     hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
  •     hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  •     hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  •     hdma_usart1_rx.Init.Mode = DMA_NORMAL;
  •     hdma_usart1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
  •     if (HAL_DMA_Init( hdma_usart1_rx) != HAL_OK)
  •     {
  •       Error_Handler();
  •     }

  •     __HAL_LINKDMA(irdaHandle,hdmarx,hdma_usart1_rx);

  •     /* USART1_TX Init */
  •     hdma_usart1_tx.Instance = DMA1_Channel4;
  •     hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  •     hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  •     hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
  •     hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  •     hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  •     hdma_usart1_tx.Init.Mode = DMA_NORMAL;
  •     hdma_usart1_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
  •     if (HAL_DMA_Init( hdma_usart1_tx) != HAL_OK)
  •     {
  •       Error_Handler();
  •     }

  •     __HAL_LINKDMA(irdaHandle,hdmatx,hdma_usart1_tx);
  •     /* USER CODE BEGIN USART1_MspInit 1 */
  •     HAL_IRDA_Receive_DMA(irdaHandle, irda1_rx_buffer, IRDA_UART_RX_SIZE);        //使能DMA接受,将接受到的数据放到irda1_rx_buffer
  •     /* USER CODE BEGIN USART1_MspInit 1 */

  •     /* USART1 interrupt Init */
  •     HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
  •     HAL_NVIC_EnableIRQ(USART1_IRQn);

  •   /* USER CODE BEGIN USART1_MspInit 1 */
  •     __HAL_UART_ENABLE_IT(irdaHandle, IRDA_IT_IDLE);                                                   //usart1, 使能空闲中断
  •                 __HAL_UART_CLEAR_IDLEFLAG(irdaHandle);
  •   /* USER CODE END USART1_MspInit 1 */
  •   }



  • void USART1_IRQHandler(void)
  • {
  •   /* USER CODE BEGIN USART1_IRQn 0 */
  •         if (__HAL_UART_GET_FLAG( hirda1, UART_FLAG_IDLE))
  •         {
  •                 __HAL_UART_CLEAR_IDLEFLAG( hirda1);
  •                 HAL_IRDA_DMAStop ( hirda1);

  •                 irda1_data_cnt = IRDA_UART_RX_SIZE - __HAL_DMA_GET_COUNTER( hdma_usart1_rx);
  •                 if (irda1_data_cnt < 6)
  •                 {
  •                         print_hex(irda1_rx_buffer, irda1_data_cnt);
  •                 }
  •                 else
  •                 {
  •                         BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  •                         xEventGroupSetBitsFromISR (irda_event_gourpHandler,
  •                         EVENT_GROUP_BIT_IRDA1_DATA,
  •                                                                                                                                   xHigherPriorityTaskWoken);
  •                 }

  •                 hdma_usart1_rx.Instance->CNDTR = IRDA_UART_RX_SIZE;
  •                 HAL_IRDA_Receive_DMA ( hirda1, irda1_rx_buffer, IRDA_UART_RX_SIZE);
  •         }
  •   /* USER CODE END USART1_IRQn 0 */
  •   HAL_IRDA_IRQHandler( hirda1);
  •   /* USER CODE BEGIN USART1_IRQn 1 */

  •   /* USER CODE END USART1_IRQn 1 */
  • }



  • void irda_modbus_parse_task(void const *argument)
  • {
  •         irda_event_gourpHandler = xEventGroupCreate();

  •         if(irda_event_gourpHandler == NULL)
  •         {
  •                 app_err("create irda_event_gourp fail!rn");
  •                 goto error;
  •         }

  •         xEventGroupClearBits(irda_event_gourpHandler, EVENT_GROUP_BIT_IRDA1_DATA|EVENT_GROUP_BIT_IRDA2_DATA);

  •         while(1)
  •         {
  •                 EventBits_t bits = xEventGroupWaitBits(irda_event_gourpHandler, EVENT_GROUP_BIT_IRDA1_DATA|EVENT_GROUP_BIT_IRDA2_DATA, pdFALSE, pdFALSE, portMAX_DELAY);

  •                 if(bits   EVENT_GROUP_BIT_IRDA1_DATA)
  •                 {
  •                         app_debug("irda1 recv datarn");
  •                         xEventGroupClearBits(irda_event_gourpHandler, EVENT_GROUP_BIT_IRDA1_DATA);
  •                         Modbus_Master_Service(irda1_rx_buffer, irda1_data_cnt, 1);
  •                         memset(irda1_rx_buffer, 0, sizeof(irda1_rx_buffer));
  •                 }
  •                 else if(bits   EVENT_GROUP_BIT_IRDA2_DATA)
  •                 {
  •                         app_debug("irda2 recv datarn");
  •                         xEventGroupClearBits(irda_event_gourpHandler, EVENT_GROUP_BIT_IRDA2_DATA);
  •                 }
  •                 else
  •                 {
  •                         xEventGroupClearBits(irda_event_gourpHandler, ~(EVENT_GROUP_BIT_IRDA1_DATA|EVENT_GROUP_BIT_IRDA2_DATA));
  •                         app_err("UNEXPECTED EVENTrn");
  •                 }
  •         }

  •         error:
  •         vEventGroupDelete(irda_event_gourpHandler);
  •         osThreadTerminate (irda_modbus_parseTaskHandle);
  • }


  • void Modbus_SendData(uint8_t *buf, int len, char direction)
  • {
  •         int res  = 0;

  •          if(direction == 1)
  •          {
  •                  res = HAL_IRDA_Transmit_DMA( hirda1, buf, len);
  •                  if(res != 0)
  •                  {
  •                          app_err("uart1 error: %drn", res);
  •                  }
  •          }
  •          else if(direction == 2)
  •          {
  •                  HAL_IRDA_Transmit_DMA ( hirda2, buf, len);
  •          }
  •          else if(direction == 3)
  •          {
  •                  HAL_IRDA_Transmit_DMA ( hirda1, buf, len);
  •                  HAL_IRDA_Transmit_DMA ( hirda2, buf, len);
  •          }
  • }





回帖(2)

欧竞仲

2024-4-10 09:59:26
现象就是正常运行,命令A发送成功,收到回复,在解析回复并执行发送命令B后,出现B发送失败情况,且单步调试发送时,反而是正常的可以发送成功的
举报

王秀珍

2024-4-10 10:49:11
从代码中没有具体看到发送命令的部分,因此不清楚您是如何发送命令的。不过,根据您的描述,有几个可能的原因导致发送失败:

1. 任务优先级问题:在使用FreeRTOS进行任务管理时,如果发送命令的任务和其他任务的优先级不合适,可能会导致发送失败。请确保发送命令的任务的优先级高于其他任务,以确保它能够及时得到执行。

2. 接收任务导致发送失败:如果接收命令的任务和发送命令的任务共享相同的串口资源,它们可能会发生竞争条件。请确保在发送命令之前,接收任务已经完成并释放了串口资源。

3. 数据缓冲区溢出:如果发送命令的数据缓冲区没有足够的空间来存储要发送的数据,那么发送命令可能会失败。请确保数据缓冲区的大小足够大,并且及时清空已发送的数据。

4. DMA配置问题:如果使用DMA进行串口数据传输,确保DMA配置正确并在发送完成后正确清除DMA标志位。

5. 串口配置问题:确保串口的波特率、数据位、停止位和校验位等配置与上位机的配置一致。使用HAL库时,可以使用HAL_IRDA_Init函数对串口进行配置。

您可以通过添加调试输出或利用串口中断来进一步调查发送失败的原因。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分