STM32USART+DMA实现不定长数据接收/发送

STM32USART+DMA实现不定长数据接收

这一期的内容是一篇代码分享,CubeMX配置介绍,关于基础的内容可以往期内容

CubeMX配置



其余部分配置这里不做介绍,这里只展示串口+DMA部分

代码分享

  1. main函数
c 复制代码
/* USER CODE BEGIN PTD */
 uint8_t Usart1_Send_Buffer[] = "公主王子请点赞!!!\r\n";
 
 uint8_t Recv_Buff[BUFFER_SIZE];  //接收数据缓存
 volatile uint8_t Recv_Length;  //接收一帧数据的长度
 volatile uint8_t Recv_DndFlag; //一帧数据接收完成标志

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();
  __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能串口空闲中断
  HAL_UART_Receive_DMA(&huart1,Recv_Buff,BUFFER_SIZE);  //开启DMA串口接收,最大接收长度为 BUFFER_SIZE
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {       
      //通过串口1使用DMA的方式发送数据
//      HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Usart1_Send_Buffer, sizeof(Usart1_Send_Buffer)); 
//    HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/* USER CODE END PTD */

在main函数定义的数据,需要在mian.h里面声明外部变量

c 复制代码
#define BUFFER_SIZE 256
extern uint8_t Recv_Buff[BUFFER_SIZE];  //接收数据缓存
extern volatile uint8_t Recv_Length;  //接收一帧数据的长度
extern volatile uint8_t Recv_DndFlag; //一帧数据接收完成标志
  1. USART1_IRQHandler中断函数
c 复制代码
void USART1_IRQHandler(void)    
{
  /* USER CODE BEGIN USART1_IRQn 0 */
    
    //注意要在USART1_IRQHandler函数内判断串口空闲中断idle的状态,而不是到串口接收完成回调函数里面,
    //由于接收长度的限制,所以大概率是不会接收完成的
//    uint32_t temp;
    if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET))//idle标志被置位为1,则说明接收完成,串口处于空闲状态
    { 
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
        
        HAL_UART_DMAStop(&huart1); //接收完成,关闭DMA串口接收   
        Recv_Length  =  BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //总计数减去未传输的数据个数,得到已经接收的数据个数
        //__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);用于获取本次DMA传输中为传输的数据个数。
        Recv_DndFlag  = 1;   // 接受完成标志位置1    
        HAL_UART_Transmit_DMA(&huart1, Recv_Buff, Recv_Length);
        Recv_Length = 0;//清除计数
        Recv_DndFlag = 0;//清除接收结束标志位 ,也可以在其他地方判断,执行相应步骤后清除。

        memset(Recv_Buff,0,Recv_Length);
        HAL_UART_Receive_DMA(&huart1, Recv_Buff, BUFFER_SIZE);//重新打开DMA接收,不然只能接收一次数据
     }
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

USART1_IRQHandler中断函数在stm32f4xx_it.c文件中,代码实现原理具体如下:

  • 开启串口1的空闲中断
  • 开启DMA串口1的接收数据,接收数据长度为BUFFER_SIZE(需要确保BUFFER_SIZE >正常的数据长度)
  • 在数据的接收过程中,串口处于忙碌状态,当接收完成时,串口空闲,发送中断。
  • 判断是空闲中断标志位置位,读取未完成传输的数据,计算接收的数据长度
  • 将计算数据长度的发送会串口,检验数据正确性
  • 清空接收的数据,再次开启DMA接收,重复以上过程。

实践结果

发送数据

接收数据

相关推荐
csg110744 分钟前
高效驱动,灵活控制:深度解析RZ7899大电流DC双向马达驱动芯片及其创新应用
单片机·嵌入式硬件·物联网
心疼你的一切1 小时前
三菱FX5U PLC与C#通信开发指南
开发语言·单片机·c#
JSMSEMI113 小时前
JSM9N20C 200V N 沟道 MOSFET
单片机·嵌入式硬件
梁下轻语的秋缘3 小时前
I2S与I2C
运维·stm32·单片机·51单片机
chipsense3 小时前
机器人用霍尔电流传感器,能提升操作安全性么?
单片机·嵌入式硬件·人形机器人·霍尔电流传感器
Zeku4 小时前
20251222 - 韦东山Linux开发板I.MX6ULL连接无线WiFi
stm32·freertos·linux驱动开发·linux应用开发
许商4 小时前
【stm32】cmake脚本(二)
stm32·单片机·嵌入式硬件
Zeku4 小时前
20251222 - 常用命令“source etcprofile”的详细解析
stm32·freertos·linux驱动开发·linux应用开发
袖手蹲4 小时前
Arduino UNO Q 讲好中国儿童故事
人工智能·单片机
TEC_INO5 小时前
STM32_4:ESP8266-WIFI模块
stm32·单片机·嵌入式硬件