STM32基于HAL库的USART+DMA使用

开发板:正点原子阿波罗

创建工程

使能USART

开启DMA

配置中断

以上配置好之后,点击生成工程

一、接收、发送指定长度数据

指定接收、发送的数据长度为1

定义一个接收缓冲区

char tx_buffer[10];

编写中断回调函数

当触发接收中断时,将接收到的数据通过DMA发送出去

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
          
   
	if (huart->Instance == USART1) {
          
   
		//函数要使用DMA方式的
		HAL_UART_Transmit_DMA(&huart1,tx_buffer,1);  
	}
}

当触发发送中断时,使用DMA接收一下

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
          
   
	if (huart->Instance == USART1) {
          
   
		函数要使用DMA方式的
		HAL_UART_Receive_DMA(&huart1,tx_buffer,1);
	}
}

使能接收中断

在main.c中

编译、下载进去就能看到效果

二、接收、发送不定长度数据

接收不定长度时,需要判断USART什么时候为空闲状态,当触发空闲中断时,证明此时已经接收全部数据,需要

用到的函数有

HAL_UART_DMAStop(UART_HandleTypeDef *huart); //停止DMA传输
__HAL_DMA_GET_COUNTER(__HANDLE__);           //得到DMA传输了多少数据
__HAL_UART_CLEAR_IDLEFLAG(__HANDLE__);       //清除空闲标志
HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size); //使用DMA的方式发送
HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);    //使用DMA的方式接收

使能空闲中断

在 MX_USART1_UART_Init() 函数中添加

/* USER CODE BEGIN USART1_Init 2 */
  //使能空闲中断
  __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
  /* USER CODE END USART1_Init 2 */

定义一个接收缓冲区

/* USER CODE BEGIN 0 */
#define RXSIZE  1024   /
uint8_t rx_buffer[RXSIZE] = {
          
   0};
uint16_t RxNum = 0;
/* USER CODE END 0 */

编写USART1中断

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
          
   
	/* USER CODE BEGIN USART1_IRQn 0 */
	
	//判断空闲标志
	if (__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) == SET) {
          
   
		//清除空闲中断标志
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);
		//停止DMA
		HAL_UART_DMAStop(&huart1);
		//接收了多长的数据
		RxNum = RXSIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
		//将接收到的数据再发送出去
		HAL_UART_Transmit_DMA(&huart1,rx_buffer,RxNum);
	}
	/* USER CODE END USART1_IRQn 0 */
	HAL_UART_IRQHandler(&huart1);
	/* USER CODE BEGIN USART1_IRQn 1 */
	/* USER CODE END USART1_IRQn 1 */
}

编写中断回调函数

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
          
   
  if (huart->Instance == USART1) {
          
   
    RxNum = 0;
    //清空一个缓冲区
    memset(rx_buffer,0,RXSIZE);
    //使能接收
    HAL_UART_Receive_DMA(&huart1,rx_buffer,RXSIZE);
  }
}

使能接收中断

在main.c中

若是不添加这句则无法进入中断 编译、下载进去就能看到效果

经验分享 程序员 微信小程序 职场和发展