STM32 CubeMX学习实验8:USART-DMA接收不定长度字节的数据

本文介绍了如何在STM32F4xx开发板上配置USART1,启用DMA并利用串口空闲中断实现数据的高效传输。通过自定义中断处理函数,确保了数据传输的完整性和DMA的重新启动。

 一、工程配置

开启USART1,打开串口中断,打开DMA request,选择USART1_RX,模式选择Normal,其他选项默认即可。

 

 

二、添加代码

1.使用USART DMA传输数据,可以通过串口的空闲中断来判断数据传输结束,要在DMA开始传输之前使能串口空闲中断,在main函数中添加代码:

  /* USER CODE BEGIN 2 */
  /*为了方便,把头文件放在此处*/
  #include "usart_it.h"
  
    //使能串口空闲中断
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
    //开启DMA传输
    HAL_UART_Receive_DMA(&huart1, USART1_Stru.RxBuff, 200);
  /* USER CODE END 2 */

使能串口空闲中断和开启一次DMA传输。

2.新建一个.c/.h文件,在.c文件中自定义一个空闲中断处理函数,用于判断数据传输结束。

void USART1_IDLE_Handler()
{
    if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))   //判断是否是空闲中断
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);                     //清除空闲中断标志(否则会一直不断进入中断)
        HAL_UART_DMAStop(&huart1);

        //获取数据长度
        USART1_Stru.RxLen = 200 - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);

        //数据回传
        HAL_UART_Transmit(&huart1,USART1_Stru.RxBuff,USART1_Stru.RxLen,1000);

        HAL_UART_Receive_DMA(&huart1, USART1_Stru.RxBuff, 200);           //重启开始DMA传输
    }
}

该函数需要放到串口中断回调中进行判断,在stm32f4xx_it.c中找到USART1_IRQHandler函数,将自定义的处理函数放到USART1_IRQHandler里。

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
    #include "usart_it.h"
    USART1_IDLE_Handler();
  /* USER CODE END USART1_IRQn 1 */
}

 编译过程可能会出现标识符hdma_usart1_rx未定义的错误,需要在usart.h中添加extern关键字进行声明

 

 下面是串口管理文件(.c/.h)的完整代码

#include "usart_it.h"
#include <stdio.h>

#if 1
#pragma import(__use_no_semihosting)   // 确保没有从 C 库链接使用半主机的函数

int fputc(int ch,FILE *p)  //函数默认的,在使用printf函数时自动调用
{
    USART1->DR = (uint8_t) ch;//发送
	while((USART1->SR & 0X40) == 0);//等待发送完成
	return ch;
}

FILE __stdout;

struct __FILE
{
    int handle;
};

//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
    x=x;
}
#endif


USART1_Structure USART1_Stru = { 0 };

void USART1_IDLE_Handler()
{
    if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))   //判断是否是空闲中断
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);                     //清除空闲中断标志(否则会一直不断进入中断)
        HAL_UART_DMAStop(&huart1);

        //获取数据长度
        USART1_Stru.RxLen = 200 - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);

        //数据回传
        HAL_UART_Transmit(&huart1,USART1_Stru.RxBuff,USART1_Stru.RxLen,1000);

        HAL_UART_Receive_DMA(&huart1, USART1_Stru.RxBuff, 200);           //重启开始DMA传输
    }
}




#ifndef _USART_IT_H
#define _USART_IT_H

#include "main.h"
#include "usart.h"


//最大接收数据长度
#define USART1RxLEN 200

typedef struct
{
    uint8_t receive;
    uint8_t RxBuff[USART1RxLEN];
    uint8_t RxLen;
}USART1_Structure;
extern USART1_Structure USART1_Stru;

void USART1_IDLE_Handler(void);




#endif




三、实验现象

通过串口调试助手发送不固定长度的数据,单片机接收到后回传到调试助手。

这期的学习就到这里,下期学习ADC读取电压。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值