yann-qu

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  1. 开启串口,是能串口全局中断

  2. 配置DMA并勾选Memory选项
    image

  3. 继续配置工程并且生成代码

  4. 添加一些串口通讯使用的全局变量

    #define BUFFER_SIZE 128
    uint8_t          Tx_Buf[50]          = {0};
    volatile uint8_t rx_len              = 0; //接收数据长度
    volatile uint8_t recv_end_flag       = 0; //接收完成标记位
    uint8_t          rx1_buffer[BUFFER_SIZE]; //接收缓存
    
  5. 在主函数中开启串口中断和DMA接收

    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);        // 使能idle中断
    HAL_UART_Receive_DMA(&huart1, Rx_Buf, BUFFER_SIZE); // 打开DMA接收
    

    注意:
    CubeMX生成的代码先初始化了串口再初始化DMA,会导致串口只能接收到最后一个字符的数据。这里需要将默认的初始化顺序调整一下,先初始化DMA,再初始化串口,即更改为:

    MX_DMA_Init();
    MX_USART1_UART_Init();
    

    参考:DMA初始化顺序问题

  6. 在中断处理函数中将串口数据存入缓冲区

    /**
    * @brief This function handles USART1 global interrupt.
    */
    void USART1_IRQHandler(void)
    {
    /* USER CODE BEGIN USART1_IRQn 0 */
    uint32_t tmp_flag = 0;
    uint32_t temp;
    tmp_flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE); //获取IDLE标志位
    if ((tmp_flag != RESET)) {
      // idle标志被置位
      __HAL_UART_CLEAR_IDLEFLAG(&huart1); //清除标志位
      temp = huart1.Instance->SR;         //清除状态寄存器SR
      temp = huart1.Instance->DR;         //读取数据寄存器中的数据
      HAL_UART_DMAStop(&huart1);
      temp          = hdma_usart1_rx.Instance->NDTR; //获取DMA中未传输的数据个数
      rx_len        = BUFFER_SIZE - temp;            //得到已经接收的数据个数
      recv_end_flag = 1;                             //接受完成标志位置1
    }
    
    /* USER CODE END USART1_IRQn 0 */
    HAL_UART_IRQHandler(&huart1);
    /* USER CODE BEGIN USART1_IRQn 1 */
    
    /* USER CODE END USART1_IRQn 1 */
    }
    
  7. 在主函数中轮询或在另一个线程中处理接收完成的数据

    if (recv_end_flag == 1) {
       printf("rx_len=%d\r\n", rx_len);                 //打印接收长度
       HAL_UART_Transmit(&huart1, Rx_Buf, rx_len, 200); //接收数据打印出来
       // TODO: 处理接收到的数据
       for (uint8_t i = 0; i < rx_len; i++) {
         Rx_Buf[i] = 0; //清接收缓存
       }
       rx_len        = 0;                                  //清除计数
       recv_end_flag = 0;                                  //清除接收结束标志位
       HAL_UART_Receive_DMA(&huart1, Rx_Buf, BUFFER_SIZE); //重新打开DMA接收
    }
    
  8. 数据处理结束后要重新打开DMA

    HAL_UART_Receive_DMA(&huart1, Rx_Buf, BUFFER_SIZE); //重新打开DMA接收
    
posted on 2022-01-25 22:44  yann-qu  阅读(620)  评论(0编辑  收藏  举报