【STM32笔记】STM32的串口数据收发基础(四)(USART DMA模式)


  在STM32中编写串口通信数据收发有三种方式:轮询模式(阻塞方式),中断模式(非阻塞方式)以及DMA模式

一. 串口通信(DMA模式)


  打开STM32CubeMX,前部分配置流程如串口数据收发基础(三)节里一样。配置好USART1的基本参数,开启定时器中断后,接下来就要开启USART1的DMA。
在这里插入图片描述在这里插入图片描述
设置好之后,设置存储路径,选择所用IDE,然后点击GENERATE CODE创建工程,open project打开工程进行全局编译。

二. HAL库中串口收发的重要函数(DMA模式)

  1. DMA模式下发送数据函数:HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

@简介  以DMA模式发送一定数量的数据。
@参数  huart,指向UART_HandleTypeDef结构体的指针,该结构体包含指定UART模块的配置信息。
@参数  pData,待发送数据缓冲区的指针。
@参数  Size,待发送数据的字节数。
@返回值  函数执行状态。

  2. DMA模式下接收数据函数: HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

@简介  在DMA模式下接收一定数量的数据
@参数  huart,指向UART_HandleTypeDef结构体的指针,该结构体包含指定UART模块的配置信息。
@参数  pData,待接收接收数据缓冲区的指针。
@参数  Size,待接收数据的字节数。
@注意  当UART奇偶校验使能(PCE = 1)时,接收的数据包含奇偶校验位。
@返回值  函数执行状态。

  3. DMA模式下接收不定长数据函数: HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

@简介  在DMA模式下接收一定数量的数据,直到接收到预期数量的数据或发生IDLE事件。
@注意  接收数据由这个函数调用发起。DMA服务实现了接收数据的进一步进展,在用户接收缓冲区中自动传输接收到的数据元素,并在接收传输过半/完成时调用回      
      调函数。UART IDLE事件也用于将接收阶段视为结束。在所有情况下,回调执行将指示接收到的数据元素的数量。
@参数  huart 指向UART_HandleTypeDef结构体的指针,该结构体包含指定UART模块的配置信息。
@参数  pData 待接收接收数据缓冲区的指针。
@参数  Size  待接收数据的字节数。
@返回值  函数执行状态。

  4. DMA模式数据传输完成回调函数:HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size);

__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
  UNUSED(huart);
  UNUSED(Size);
}

@简介  接收事件回调(使用高级接收服务后调用的Rx事件通知)。
@参数  huart UART handle
@参数  Size,应用程序接收缓冲区中可用数据的数量(表示接收缓冲区中数据可用的位置)
@返回值  空

  5.禁用指定的DMA通道中断函数:__HAL_DMA_DISABLE_IT(HANDLE, INTERRUPT) (CLEAR_BIT((HANDLE)->Instance->CCR , (INTERRUPT)));

#define __HAL_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__)  (CLEAR_BIT((__HANDLE__)->Instance->CCR , (__INTERRUPT__)))

@简介  禁用指定的DMA通道中断。
@参数  __HANDLE__: DMA处理
@参数  __INTERRUPT__: 指明要启用或者禁用的DMA中断源
该参数可以是下列值的任意组合:
    @arg DMA_IT_TC:  传输完成中断屏蔽
    @arg DMA_IT_HT:  过半传输完成中断屏蔽
    @arg DMA_IT_TE:  传输错误中断屏蔽
@返回值  空

以上提及的函数可在stm32f1xx_hal_uart.cstm32f1xx_hal_dma.h中,在这些文件中找到
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

三. 实现串口定长收发通信(DMA模式)

在main.c文件中的Private variables下的USER CODE BEGIN PV注释对中写入以下代码

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
unsigned char String_1[] = "hello world!!!\r\n";
unsigned char rx[16];
/* USER CODE END PV */

在main.c文件中的Private function prototypes下的USER CODE BEGIN PFP注释对中写入以下代码

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// dma模式
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
	if(huart == &huart1){ //  将上位机发来的数据完整的返回回去
		HAL_UART_Transmit_DMA(&huart1,rx,sizeof(rx));
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_4);
		HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
	}
}
/* USER CODE END PFP */

在main.c文件中的main函数下USER CODE BEGIN 2 注释对写入以下代码

/* USER CODE BEGIN 2 */
  HAL_UART_Transmit_IT(&huart1,String_1,sizeof(String_1));
  HAL_UART_Receive_DMA(&huart1,rx,sizeof(rx));
/* USER CODE END 2 */

实现的效果是在当开发板通过USB转TTL模块与电脑上的串口调试助手相连后,上位机向开发板发送的数据。开发板接收到上位机发来的数据后,翻转PB4引脚上的LED灯亮灭,随后将接收到的数据原封不动的再返回给上位机。
在这里插入图片描述

四. 实现串口不定长收发数据通信(DMA模式)

在main.c文件中的Private function prototypes下的USER CODE BEGIN PFP注释对中写入以下代码

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// dma模式
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
	if(huart == &huart1){ //  将上位机发来的数据完整的返回回去
		HAL_UART_Transmit_DMA(&huart1,rx,Size);
		HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
	}
}
/* USER CODE END PFP */

在main.c文件中的main函数下USER CODE BEGIN 2 注释对写入以下代码

/* USER CODE BEGIN 2 */
  HAL_UART_Transmit_IT(&huart1,String_1,sizeof(String_1));
  HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx,sizeof(rx));
/* USER CODE END 2 */

实现的效果是在当开发板通过USB转TTL模块与电脑上的串口调试助手相连后,上位机向开发板发送的数据。开发板接收到上位机发来的数据后,随后将接收到的数据原封不动的再返回给上位机。
如下图可以发现依次发送不定长的数据给开发板后,开发板都完整的返回了。

在这里插入图片描述
但是当我们一次发送过多的数据后,返回的数据竟然不完整了。
在这里插入图片描述
这是因为在发送数据的时候,当我们接收的数据量达到设置的最大值的一半的时候
也就是这个在这里插入图片描述
,就会触发HAL_UARTEx_RxEventCallback回调函数。
为了解决这个问题,我们可以使用关闭“DMA传输过半中断”的函数,也就是__HAL_DMA_DISABLE_IT()函数。将其写入到HAL_UARTEx_RxEventCallback回调函数中

在这里插入图片描述
注意:如果编译出错为 **error: #20: identifier “hdma_usart1_rx” is undefined **时,说明标识符“hdma_usart1_rx”未定义。可以证明解决。
在usart.h中的USER CODE BEGIN Private defines注释对中添加extern DMA_HandleTypeDef hdma_usart1_rx;
在这里插入图片描述
编译,运行,串口调试助手,启动!!!
这个时候可以发现数据终于实现了正常的不定长收发了(只要不要写过我们的先前设定的rx数组长度就好了)

在这里插入图片描述

  • 8
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: STM32 USART DMA接收数据是一种高效的数据传输方式。具体步骤如下: 1. 配置USART的接收参数,包括波特率、数据位、停止位、校验位等。 2. 配置DMA通道,设置传输方向为从USART接收数据到内存,设置传输数据长度和内存地址。 3. 启动DMA传输,等待传输完成。 4. 在DMA传输完成中断中,处理接收到的数据。 需要注意的是,在使用DMA接收数据时,需要开启USARTDMA接收中断,以便在数据接收完成后触发DMA传输完成中断。同时,还需要在程序中处理DMA传输错误中断,以确保数据传输的正确性。 以上就是STM32 USART DMA接收数据的基本步骤,希望能对您有所帮助。 ### 回答2: stm32是一款广泛应用于嵌入式系统中,功能强大的微控制器,其内置的USART模块可以实现串口通信,使用DMA(Direct Memory Access,直接内存访问)可以在USART接收数据时,将数据自动存入内存,减少CPU的参与,提高接收数据的效率。 接收数据DMA配置: 1. 选择USART接收模式:使能USART的接收中断,并清除接收中断标志位USART_CR1_RE = 1,USART_CR1_RXNEIE = 1,USART_ICR_IDLECF = 1; 2. 选择DMA通道: 发送数据是从存储器读取数据并通过USART发送,接收数据时与之相反。先选择合适的DMA通道进行配置,如:DMA1_Channel7; 3. 配置DMA数据传输方向:设置DMA数据传输方向为从外设到存储器DMA_CCR_DIR类似于串口接收,属于从外设读取数据,然后通过DMA传输到存储器中,因此需进行设置。 4. 配置存储器地址:DMA传输数据到目的地存储器的起始地址,如&rx_buff[0]; 5. 配置数据长度:设置DMA传输数据长度,如:DMA_CNDTR7 = sizeof(rx_buff); 6. 配置DMA内存地址自增模式DMA传输时,需要自动将传输的数据存储到连续的内存地址中,需要设置DMA_CCR_MINC为1,表示DMA传输时内存地址自动递增,如:DMA_CCR7 |= DMA_CCR_MINC; 7. 配置传输完成中断:DMA传输完成后触发一个中断请求,可以根据中断标志位来完成后续处理,如:DMA_CR_TCIF7 = 1; 8. 配置DMA开启:配置完成后,通过设置DMA_CCR_EN使能DMA通道,如:DMA_CCR7 |= DMA_CCR_EN; 以上就是使用DMA接收USART数据的具体步骤,除此之外,还需要在主函数中初始化串口DMA,并在中断服务函数中完成数据的处理。当接收到数据后,DMA会自动将数据存入内存中,并通过中断通知CPU做出相应的操作。这样可以节省CPU资源,提高系统的响应速度。 ### 回答3: STM32是一款由意法半导体公司(STMicroelectronics)推出的32位单片机,拥有丰富的外设接口和强大的处理能力。其中USART是串行通信的一种形式,也是STM32通信类外设中常用的一种。 在STM32中使用USART进行接收数据时,传统的方式是通过中断触发接收数据,并在中断处理函数中进行数据的处理。然而,这种方式存在一些问题,例如中断响应时延、数据丢失等。为了解决这些问题,STM32还提供了DMA(Direct Memory Access)接口,可以实现无中断干扰的数据接收。 在USART DMA接收数据过程中,我们需要先配置好UART的基本参数,例如波特率、数据位、停止位、校验位等,然后再开启DMA传输。具体步骤如下: 1.配置USART串口参数:包括波特率,数据位,停止位和校验位等参数。 2.配置DMA通道:首先选择DMA通道,然后设置DMA缓存地址和长度,这里的缓存地址是我们存储接收数据的地址。 3.开启USART DMA接收:配置好USART串口参数和DMA通道后,通过设置USARTDMA接收位(即USART_CR3寄存器中的DMAEN位)来开启USART DMA接收。 4.等待数据的接收:等待DMA完成数据的接收并存储到缓存中,可以通过DMA传输完成中断和状态标志位等方式来判断是否已经接收到数据。 5.处理数据:在DMA传输完成中断处理函数中对接收到的数据进行处理,例如打印、解析或存储等。 总体来说,使用USART DMA接收数据可以提高数据的可靠性和稳定性,也有利于系统的性能优化和资源的节约。虽然配置复杂,但是在实际应用中确实是一种十分可靠和高效的数据通信方式。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值