STM32串口IDLE中断接收+DMA(HAL库)

目录

一、CubeMX配置

二、程序编写

三、最终结果


一、CubeMX配置

1、打开异步串口,配置相关参数:

2、使能发送和接收DMA,模式配置为单次发送,也就是每次发送完之后需要手动开启DMA,这样可以使得接收数据的过程更好控制;选择Memory地址自增,也就是每存一个数据,地址指针自动加1;数据宽度选择Byte:

 3、打开串口中断,并按需配置中断优先级,然后生成代码:

二、程序编写

1、首先在usart.h中,定义所需要用到的变量,这里我定义了一个串口数据结构体,并声明为外部变量:

#define BUFFER_SIZE 1024  //Receive datas size
//Define struct of the receive data
typedef struct {
  volatile uint16_t rx_len;
  volatile uint8_t recv_end_flag;
  uint8_t* rx_buf;
}UART_RxData_t;
extern UART_RxData_t rx_datas;

2、然后在usart.c中初始化串口数据结构体,并在MX_USART2_UART_Init串口初始化函数中调用串口空闲中断函数以及开启串口DMA接收:

/* USER CODE BEGIN 0 */
uint8_t rx_buffer[BUFFER_SIZE]={0};//Define receive array
UART_RxData_t rx_datas = {  //define receive data
  .recv_end_flag = 0,
  .rx_len = 0,
  .rx_buf = rx_buffer
};

/* USER CODE END 0 */
/* USER CODE BEGIN USART2_Init 2 */
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);//Enable IDLE interrupt
HAL_UART_Receive_DMA(&huart2, rx_datas.rx_buf, BUFFER_SIZE);//Start RX DMA

/* USER CODE END USART2_Init 2 */

 3、接着去到stm32f1xx_it.c中断函数文件中,找到串口中断函数USART2_IRQHandler,并添加如下代码:

/**
  * @brief This function handles USART2 global interrupt.
  */
void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
  //IDLE interrupt
  if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) {
    __HAL_UART_CLEAR_IDLEFLAG(&huart2);
    HAL_UART_DMAStop(&huart2);  //Stop RX DMA
    //Get the receive datas len
    rx_datas.rx_len = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
    rx_datas.recv_end_flag = 1;//Mark the end of receive
  }
  
  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */
}

 4、最后在主循环中判断接收标志位是否为1,再将数据发回到上位机:

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    if(rx_datas.recv_end_flag) {
      rx_datas.recv_end_flag = 0;//Clear flag
      //Send the datas of receive
      if(HAL_OK != HAL_UART_Transmit_DMA(&huart2, rx_datas.rx_buf, rx_datas.rx_len)) {
        Error_Handler();
      }
      rx_datas.rx_len = 0;
      HAL_UART_Receive_DMA(&huart2, rx_datas.rx_buf, BUFFER_SIZE);//Start receive
    }
  }
  /* USER CODE END 3 */

 三、最终结果

 

可以看到给下位机发了700多个字符也能全部发送回上位机。

PS.代码仅作为学习记录,至于为什么心血来潮用英文写注释,完全是因为用中文写注释的时候,我用VSCode打开用CubeMX生成的新Keil工程后,中文乱码了。。。没办法,只能当作好好学习英语了~~~

以上均为个人学习心得,如有错误,请不吝赐教~

THE END

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值