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
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
引用\[1\]中的代码是一个在STM32HAL库中使用DMA接收串口数据的例子。在这个例子中,通过设置空闲中断IDLE)来判断串口接收是否完成,并使用DMA来传输数据。具体的实现步骤如下: 1. 首先,需要使能串口的空闲中断。在CUBEMX软件中,没有提供图形界面来开启空闲中断,所以需要手动编写代码来开启。 2. 接下来,开启DMA接收功能。通过调用HAL_UART_Receive_DMA函数来启动DMA接收,将接收到的数据存储到指定的缓冲区中。 3. 当串口接收到数据后,会触发空闲中断。在空闲中断处理函数中,首先需要清除中断标志,然后停止DMA接收。 4. 接着,通过调用__HAL_DMA_GET_COUNTER函数来获取DMA接收剩余的字节数,从而计算出实际接收到的字节数。 5. 然后,可以对接收到的数据进行处理,比如将数据发送到其他串口。 需要注意的是,根据实际接收到的字节数来定义DMA_RECEIVE的大小,确保其能够容纳接收到的数据。在引用\[1\]中,使用了uint16_t类型来定义DMA_RECEIVE。 总的来说,这个例子展示了如何使用STM32HAL库中的DMA接收串口数据,并通过空闲中断来判断接收是否完成。希望对正在学习的人有所帮助。 #### 引用[.reference_title] - *1* *3* [STM32 HAL库 串口DMA接收不定长数据](https://blog.csdn.net/weixin_41872408/article/details/118739340)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [STM32HAL库开发系列 - 串口DMA接收](https://blog.csdn.net/sorcererr/article/details/128698094)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~O'Connor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值