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

实践结果

发送数据

接收数据

相关推荐
景彡先生12 分钟前
STM32中SPI协议详解
stm32·单片机·嵌入式硬件
趣多多代言人15 分钟前
嵌入式面试八股文100题(二)
单片机·嵌入式硬件
Star Curry1 小时前
【新手小白的嵌入式学习之路】-STM32的学习_GPIO 8种模式学习心得
stm32·嵌入式硬件·学习
ZERONG_H1 小时前
STM32固件升级设计——内部FLASH模拟U盘升级固件
stm32·单片机·嵌入式硬件
猫猫的小茶馆2 小时前
【STM32】ADC模数转换基本原理
stm32·单片机·嵌入式硬件·mcu·51单片机
不想学习\??!2 小时前
STM32-USART
stm32·单片机·嵌入式硬件
网硕互联的小客服2 小时前
服务器经常出现蓝屏是什么原因导致的?如何排查和修复?
运维·服务器·stm32·单片机·网络安全
YTao_G3 小时前
STM32模块:018 I2C通信Part.02实验
stm32·单片机·嵌入式硬件
Do vis8244 小时前
STM32第十八天 ESP8266-01S和电脑实现串口通信
stm32·单片机·嵌入式硬件
xyx-3v12 小时前
VS CodeC51 单片机开发环境搭建
单片机·嵌入式硬件