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

实践结果

发送数据

接收数据

相关推荐
JNX_SEMI10 小时前
EG2226 全桥驱动芯片技术解析:600V/1A 耐压、SSOP16 封装,助力逆变器与无刷电机驱动设计
单片机·嵌入式硬件·物联网
大卡片11 小时前
PWM控制原理
嵌入式硬件
周周记笔记13 小时前
【元器件专题】用阻抗等效分析法来分析开关电路
单片机·嵌入式硬件
leoFY12313 小时前
STM32H750配置LAN PHY芯片LAN8742
网络·stm32·嵌入式硬件
iCxhust13 小时前
如何利用iret修改cs ip
汇编·单片机·嵌入式硬件·微机原理·8088单板机
m0_3771081415 小时前
stm32平衡车
stm32·单片机·嵌入式硬件
小+不通文墨16 小时前
把树莓派外接的DHT11接收的温湿度发送到emqx上
经验分享·笔记·嵌入式硬件·学习·树莓派
Deitymoon16 小时前
FreeRTOS——列表与列表项
stm32·单片机·嵌入式硬件
总结所学16 小时前
电路定理 叠加定理 基尔霍夫定律
单片机·嵌入式硬件
加成BUFF19 小时前
机器人专业2025年12月5日《嵌入式系统STM32》期末考试范围+试卷
stm32·嵌入式·期末复习