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接收,重复以上过程。

实践结果

发送数据

接收数据

相关推荐
FreakStudio4 小时前
全网最适合入门的面向对象编程教程:56 Python字符串与序列化-正则表达式和re模块应用
python·单片机·嵌入式·面向对象·电子diy
EVERSPIN7 小时前
分享国产32位单片机的电机控制方案
单片机·嵌入式硬件
每天一杯冰美式oh7 小时前
51单片机的家用煤气报警系统【proteus仿真+程序+报告+原理图+演示视频】
嵌入式硬件·51单片机·proteus
芯橦10 小时前
【瑞昱RTL8763E】音频
单片机·嵌入式硬件·mcu·物联网·音视频·visual studio code·智能手表
夜间去看海14 小时前
基于单片机的智能浇花系统
单片机·嵌入式硬件·智能浇花
VirtuousLiu14 小时前
LM74912-Q1用作电源开关
单片机·嵌入式硬件·ti·电源设计·lm74912·电源开关
打地基的小白14 小时前
软件I2C-基于江科大源码进行的原理解析和改造升级
stm32·单片机·嵌入式硬件·通信模式·i2c
Echo_cy_15 小时前
STM32 DMA+AD多通道
stm32·单片机·嵌入式硬件
朴人15 小时前
【从零开始实现stm32无刷电机FOC】【实践】【7.2/7 完整代码编写】
stm32·单片机·嵌入式硬件·foc
追梦少年时15 小时前
STM32中断——外部中断
stm32·单片机·嵌入式硬件