hzp2022 2024-03-17 10:00 采纳率: 46.2%
浏览 49
已结题

STM32串口堵塞和非堵塞的一个问题

请问一下32串口发送的问题,为什么我在mian函数中使用三种不同的发送模式按顺序发送,第一次没有加delay函数,我发现IT中断发送的内容串口中就打印不出来,第二次加了delay三个就都能发送出来了,这是为什么呢?有没有人能解释一下?


int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
    HAL_UART_Transmit(&huart1,(uint8_t*)"usart ok\n\r",strlen("usart ok\n\r"),999);
    HAL_Delay(10);
    HAL_UART_Transmit_DMA(&huart1,(uint8_t *)"usart_DMA ok\n\r",strlen("usart_DMA ok\n\r"));
    HAL_Delay(10);
    HAL_UART_Transmit_IT(&huart1,(uint8_t*)"usart_IT ok\n\r",strlen("usart_IT ok\n\r"));

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2024-03-17 10:00
    关注

    hzp2022 上午好☀️☀️☀️️
    本答案参考ChatGPT-3.5

    在使用STM32串口发送数据时,可以选择使用阻塞或非阻塞的方式发送数据。

    阻塞方式是指在发送数据的函数中,等待数据完全发送出去后再返回,发送期间程序会一直停在这个函数中,直到数据发送完成。这样可以确保数据完整发送,但会占用较长的时间。

    非阻塞方式是指在发送数据的函数中,将数据放入发送缓冲区后立即返回,不等待数据发送完成。利用中断或DMA等机制,串口会在后台继续发送数据,发送过程不会阻塞主程序的执行。这样可以充分利用CPU的时间,提高系统的响应能力。

    在你的代码中,你分别使用了三种不同的发送模式:阻塞模式、DMA模式和中断模式

    下面是关于你的问题的解释以及解决方案:

    问题解释:第一次使用中断模式发送数据时,没有添加延迟函数,发现数据没有成功发送。第二次使用延迟函数后,三种发送模式都正常发送。

    解释:这是因为在你使用中断发送数据时,如果不添加延迟函数,主程序立即退出,中断请求可能会被覆盖或未执行完成,导致数据没有成功发送。

    解决方案:

    1. 使用中断模式发送数据时,确保主程序的执行时间足够长,等待中断请求被完整执行。可以通过添加延迟函数或让主程序进入空闲循环来实现。

    2. 另一种方法是使用DMA模式发送数据,这样可以避免中断请求被覆盖的问题。DMA会在后台独立发送数据,不会受到主程序的影响。在使用DMA模式时,不需要添加延迟函数。

    修改后的代码示例:

    int main(void)
    {
      /* 用户代码开始 --------------------------------------------------------*/
    
      /* 用户代码结束 --------------------------------------------------------*/
    
      /* MCU配置 --------------------------------------------------------------*/
    
      /* 重置所有外设,初始化闪存接口和SysTick。 */
      HAL_Init();
    
      /* 用户代码开始初始化 */
    
      /* 用户代码结束初始化 */
    
      /* 配置系统时钟 */
      SystemClock_Config();
    
      /* 用户代码开始SysInit */
    
      /* 用户代码结束SysInit */
    
      /* 初始化所有配置的外设 */
      MX_GPIO_Init();
      MX_DMA_Init();
      MX_USART1_UART_Init();
    
      /* 用户代码开始 */
      HAL_UART_Transmit(&huart1, (uint8_t*)"usart ok\n\r", strlen("usart ok\n\r"), 999);
      HAL_Delay(10);
      HAL_UART_Transmit_DMA(&huart1, (uint8_t*)"usart_DMA ok\n\r", strlen("usart_DMA ok\n\r"));
      /* 等待DMA发送完成 */
      HAL_Delay(10);
      while (HAL_UART_GetState(&huart1) != HAL_UART_STATE_READY) {
        // 等待
      }
      HAL_UART_Transmit_IT(&huart1, (uint8_t*)"usart_IT ok\n\r", strlen("usart_IT ok\n\r"));
    
      /* 无限循环 */
      while (1) {
    
      }
    }
    

    解释:在使用DMA模式发送数据后,我们通过循环检查串口状态,确保DMA发送完成后再发送中断模式发送的数据。在这种情况下不需要添加延迟函数。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 3月25日
  • 已采纳回答 3月17日
  • 创建了问题 3月17日