欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

STM32F103用hal库使用DMA+串口空闲中断接收数据

程序员文章站 2022-03-07 18:23:13
简介:出现空闲标志时,认为一帧报文发送完毕,进行报文分析,比普通的串口中断效率高很多!用到的工具:CubeMX,Keil5芯片:STM32F103VET6步骤:一、配置串口二、使能串口NVIC中断三、配置DMA四、配置为MDK5,并生成代码工程五、打开工程,添加部分代码uint8_t receive_buff[255]; //定义接收数组int main(void){ /* USER CODE BEGIN 1 */...

简介:

出现空闲标志时,认为一帧报文发送完毕,进行报文分析,比普通的串口中断效率高很多!

用到的工具:CubeMX,Keil5

芯片:STM32F103VET6

步骤:

一、配置串口STM32F103用hal库使用DMA+串口空闲中断接收数据

二、使能串口NVIC中断

STM32F103用hal库使用DMA+串口空闲中断接收数据

三、配置DMA

STM32F103用hal库使用DMA+串口空闲中断接收数据

四、配置为MDK5,并生成代码工程

STM32F103用hal库使用DMA+串口空闲中断接收数据

五、打开工程,添加部分代码

uint8_t receive_buff[255];                //定义接收数组
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();
  /* USER CODE BEGIN 2 */
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
	HAL_UART_Receive_DMA(&huart1, (uint8_t*)receive_buff, 255); 
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

STM32F103用hal库使用DMA+串口空闲中断接收数据

六、添加串口空闲中断处理

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 1 */
	if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))   //判断是否是空闲中断
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);                       //清除空闲中断标志
		HAL_UART_DMAStop(&huart1);                                //停止本次DMA传输    
		uint8_t data_length  = 255 - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);   //计算接收到的数据长度
		HAL_UART_Transmit(&huart1,receive_buff,data_length,0x200);             //测试函数:将接收到的数据打印出去
		memset(receive_buff,0,data_length);                                            
		data_length = 0;
		HAL_UART_Receive_DMA(&huart1, (uint8_t*)receive_buff, 255);                    //重启开始DMA传输
	}
  /* USER CODE END USART1_IRQn 1 */
}

七、连接串口助手测试

收到数据后,会在空闲中断里把收到的数据发送回去。效果如下图所示:

STM32F103用hal库使用DMA+串口空闲中断接收数据


以下为把串口空闲中断抽离出来:以串口2为例:

UART_HandleTypeDef huart2;
uint8_t receive_buff2[255];
DMA_HandleTypeDef hdma_usart2_rx;

void Uart2_Init()
{
	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_AFIO_CLK_ENABLE();
  __HAL_RCC_PWR_CLK_ENABLE();
	__HAL_RCC_USART2_CLK_ENABLE();
	__HAL_RCC_DMA1_CLK_ENABLE();
	HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
	
	HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
	
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = GPIO_PIN_2;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

	GPIO_InitStruct.Pin = GPIO_PIN_3;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	/* USART2 DMA Init */
    /* USART2_RX Init */
	hdma_usart2_rx.Instance = DMA1_Channel6;
	hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
	hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
	hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
	hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
	hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
	hdma_usart2_rx.Init.Mode = DMA_NORMAL;
	hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;
	if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
	{
		Error_Handler();
	}

	__HAL_LINKDMA(&huart2,hdmarx,hdma_usart2_rx);

	/* USART2 interrupt Init */
	HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
	HAL_NVIC_EnableIRQ(USART2_IRQn);
	
	
	huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
	__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);
	HAL_UART_Receive_DMA(&huart2, (uint8_t*)receive_buff2, 255); 	  
}
/**
  * @brief This function handles USART2 global interrupt.
  */
uint8_t data_length;
void USART2_IRQHandler(void)
{
	if(RESET != __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))   //判断是否是空闲中断
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart2);                       //清除空闲中断标志
		HAL_UART_DMAStop(&huart2);                                //停止本次DMA传输    
		data_length  = 255 - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);   //计算接收到的数据长度
		HAL_UART_Transmit(&huart2,receive_buff2,data_length,0x200);             //测试函数:将接收到的数据打印出去
//		memset(receive_buff2,0,data_length);                                            
		HAL_UART_Receive_DMA(&huart2, (uint8_t*)receive_buff2, 255);                    //重启开始DMA传输
	}
}

main里调用初始化即可

int main(void)
{
    int count = 1;
    Uart2_Init();
    while (1)
    {
        ...
    }
}

 

本文地址:https://blog.csdn.net/coderdd/article/details/108181763