STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号

这篇具有很好参考价值的文章主要介绍了STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一. 问题描述

能够点进这篇文章的小伙伴肯定是对STM32串口DMA空闲中断接收数据感兴趣的啦,今天用这一功能实现串口解析航模遥控器sbus信号时,查阅了很多网友发布的文章(勤劳的搬运工~),包括自己之前写过一篇博客 STM32_HAL库_CubeMx串口DMA通信(DMA发送+DMA空闲接收不定长数据)。本文进一步梳理一下HAL库串口空闲中断三种不同的使用方式,其中前两种使用DMA方式,最后一种使用HAL库自带的空闲中断机制。

本文环境:

  • Keil MDK5.14
  • STM32CubeMX6.2.1
  • 开发板/芯片:自制板/STM32F407ZGT6

实现功能:

  • 串口DMA/非DMA空闲中断接收不定长数据/解析航模遥控器SBUS信号

二. 方法一——使用HAL_UART_Receive_DMA

最常见的方法就是使用HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)这个库函数,其使用方法类似于HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size),初始化时需要调用一次,然后每次在中断服务函数里面处理完数据后重新调用一次。

使用HAL_UART_Receive_IT只需要打开串口接收中断,即HAL_NVIC_EnableIRQ(UART5_IRQn);

使用HAL_UART_Receive_DMA空闲中断需要在初始化时打开串口空闲中断使能,调用方式为:__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE)

此时DMA中断可开可不开,开了也不用管,因为数据处理是在串口空闲中断中进行的。

1. 串口初始化代码:

void MX_USART2_UART_Init(void)
{
	huart2.Instance = USART2;
	huart2.Init.BaudRate = 100000;
	huart2.Init.WordLength = UART_WORDLENGTH_9B;
	huart2.Init.StopBits = UART_STOPBITS_1;
	huart2.Init.Parity = UART_PARITY_EVEN;
	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,USART2_RX_BUF,USART_REC_LEN);		// 启动DMA接收
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
	if(uartHandle->Instance==USART2)
	{
		 __HAL_RCC_USART2_CLK_ENABLE();
		 __HAL_RCC_GPIOA_CLK_ENABLE();
		 
		 GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
		 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		 GPIO_InitStruct.Pull = GPIO_NOPULL;
		 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
		 GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
		 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
		
		 hdma_usart2_rx.Instance = DMA1_Stream5;
		 hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4;
		 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_MEDIUM;
		 hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
		 if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
		 {
		   Error_Handler();
		 }
		
		 __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx);
		
		 /* USART2 interrupt Init */
		 HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
		 HAL_NVIC_EnableIRQ(USART2_IRQn);
	}
}

初始化中调用__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE)开启空闲中断,HAL_UART_Receive_DMA(&huart2,USART2_RX_BUF,USART_REC_LEN)启动DMA串口接收,USART2_RX_BUF是接收缓冲区,USART_REC_LEN是定义的DMA接收缓冲区长度,接收的数据不能超过这个长度。

2. 中断处理:

中断处理有两种方式,第一种是直接定义在void USART1_IRQHandler(void)中,第二种是自定义一个函数,然后在void USART1_IRQHandler(void)中调用。注意网上很多资源自定义了中断回调函数但代码又没贴全,读者可能以为是HAL库自带的回调函数,结果因为没有在void USART1_IRQHandler(void)中调用导致失败。

第一种形式——直接定义:

void USART2_IRQHandler(void)
{
	uint32_t tmp_flag ;
	u8 len;
	u8 data[25];
	tmp_flag  = __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE);

	if( tmp_flag  != RESET)
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除标志位
		HAL_UART_DMAStop(&huart2); //停止DMA接收,防止数据出错
	
		len = USART_REC_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);// 获取DMA中传输的数据个数
		
		// 以下为用户数据处理,将数据拷贝出去
		if(len == 25)
		{
			memcpy(data,USART2_RX_BUF,len);
			update_sbus(data);
		}
		HAL_UART_Receive_DMA(&huart2,USART2_RX_BUF,USART_REC_LEN);   //打开DMA接收,数据存入rx_buffer数组中。
	}
	
	HAL_UART_IRQHandler(&huart2); //调用HAL库中断处理公用函数
}

第二种形式——自定义回调函数:

void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)
{
	uint32_t tmp_flag ;
	u8 len;
	u8 data[25];

	if (huart->Instance == USART2)
	{
		tmp_flag  = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE);
		if( tmp_flag  != RESET)
		{
			__HAL_UART_CLEAR_IDLEFLAG(huart);//清除标志位
			HAL_UART_DMAStop(huart); //停止DMA接收
		
			len = USART_REC_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);// 获取DMA中传输的数据个数
			
			// 以下为用户数据处理,将数据拷贝出去
			if(len == 25)
			{
				memcpy(data,USART2_RX_BUF,len);
				update_sbus(data);
			}
			HAL_UART_Receive_DMA(huart,USART2_RX_BUF,USART_REC_LEN);   //打开DMA接收,数据存入rx_buffer数组中。
		}
	}
}

void USART2_IRQHandler(void)
{
	HAL_UART_IdleCpltCallback(&huart2)
	HAL_UART_IRQHandler(&huart2); //调用HAL库中断处理公用函数
}

再次提醒一下,HAL库中并没有类似void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)这样的回调函数,大家不要看到了以为是自带的回调函数而不在void USART2_IRQHandler(void)中调用而导致失败。

中断处理中的函数说明:
__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE):返回中断标志位,产生空闲中断后会返回1;
__HAL_UART_CLEAR_IDLEFLAG(&huart2):清除空闲中断标志位,必须调用;
HAL_UART_DMAStop(&huart2):停止DMA接收,防止数据处理出错,数据处理完成后重新打开;
__HAL_DMA_GET_COUNTER(&hdma_usart2_rx):返回DMA中未传输的数据量,用缓冲区总长减去未传输数量就是已接收的数据长度;
HAL_UART_Receive_DMA(huart,USART2_RX_BUF,USART_REC_LEN):重新打开DMA接收。

以上就能成功实现不定长数据的接受了,其实只要步骤对了还是很简单的。

三. 方法二——使用HAL_UARTEx_ReceiveToIdle_DMA

第二种方式是使用HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)这个库函数,并重定义void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)这个中断回调函数。

Attention:__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)是正儿八经的库函数(弱函数),不是自定义的,我们可以重定义它。

使用这个库函数,串口初始化代码中就不需要调用__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE)了,因为HAL_UARTEx_ReceiveToIdle_DMA函数内部已经打开了空闲中断,当然你加上也没事。

1. 串口初始化代码:

void MX_USART2_UART_Init(void)
{
	huart2.Instance = USART2;
	huart2.Init.BaudRate = 100000;
	huart2.Init.WordLength = UART_WORDLENGTH_9B;
	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_UARTEx_ReceiveToIdle_DMA(&huart2,USART2_RX_BUF,USART_REC_LEN);		// 使用串口DMA空闲中断,会自动开启空空闲中断
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
	if(uartHandle->Instance==USART2)
	{
		 __HAL_RCC_USART2_CLK_ENABLE();
		 __HAL_RCC_GPIOA_CLK_ENABLE();
		 
		 GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
		 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		 GPIO_InitStruct.Pull = GPIO_NOPULL;
		 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
		 GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
		 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
		
		 hdma_usart2_rx.Instance = DMA1_Stream5;
		 hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4;
		 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_MEDIUM;
		 hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
		 if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
		 {
		   Error_Handler();
		 }
		
		 __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx);
		
		 /* USART2 interrupt Init */
		 HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
		 HAL_NVIC_EnableIRQ(USART2_IRQn);
	}
}

这里__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE)是可省略的,HAL_UARTEx_ReceiveToIdle_DMA(&huart2,USART2_RX_BUF,USART_REC_LEN)启动DMA串口空闲中断接收,USART2_RX_BUF是接收缓冲区,USART_REC_LEN是定义的DMA接收缓冲区长度,接收的数据不能超过这个长度。

2. 中断处理:

中断处理定义在void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)这个中断回调函数中。

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	u8 len;
	u8 data[25];
	if(huart->Instance == USART2)
	{
		HAL_UART_DMAStop(huart);
		len = USART_REC_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);// 获取DMA中传输的数据个数
		if (USART2_RX_BUF[0] == 0x0F && len == 25)	//接受完一帧数据
		{
			memcpy(data,USART2_RX_BUF,len);
			update_sbus(data);
		}
		HAL_UARTEx_ReceiveToIdle_DMA(&huart2,USART2_RX_BUF,USART_REC_LEN);		// 再次开启DMA空闲中断
	}
}	

void USART2_IRQHandler(void)
{
	HAL_UART_IRQHandler(&huart2); //调用HAL库中断处理公用函数
}

当然也可以像方法一种一样,中断逻辑处理直接定义在void USART2_IRQHandler(void)中。

四. 方法三——使用HAL_UARTEx_ReceiveToIdle_IT(不使用DMA)

这种方法参考这篇文章: STM32 hal库串口空闲中断最新用法

使用方法:
1、在主函数中调用HAL_UARTEx_ReceiveToIdle_IT()
2、在回调函数HAL_UARTEx_RxEventCallback()中做中断逻辑处理。

这里我换用串口4,实现上位机发送,单片机原封不动返回数据。

1. 串口初始化代码:

void MX_UART4_Init(void)
{
	huart4.Instance = UART4;
	huart4.Init.BaudRate = 115200;
	huart4.Init.WordLength = UART_WORDLENGTH_8B;
	huart4.Init.StopBits = UART_STOPBITS_1;
	huart4.Init.Parity = UART_PARITY_NONE;
	huart4.Init.Mode = UART_MODE_TX_RX;
	huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart4.Init.OverSampling = UART_OVERSAMPLING_16;
	if (HAL_UART_Init(&huart4) != HAL_OK)
	{
		Error_Handler();
	}
	// HAL_UARTEx_ReceiveToIdle_IT同时开启空闲中断,开启接收
	HAL_UARTEx_ReceiveToIdle_IT(&huart4,USART4_RX_BUF,USART_REC_LEN);
}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
	if(uartHandle->Instance==UART4)
	{
		 __HAL_RCC_UART4_CLK_ENABLE();
	    __HAL_RCC_GPIOC_CLK_ENABLE();
	  
	    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
	    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	    GPIO_InitStruct.Pull = GPIO_PULLUP;
	    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	    GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
	    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
	
	    HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);
	    HAL_NVIC_EnableIRQ(UART4_IRQn);
	}
}

可以看到这里是没有使用DMA的,初始化中调用了HAL_UARTEx_ReceiveToIdle_IT(&huart4,USART4_RX_BUF,USART_REC_LEN)来开启串口4的空闲中断,USART4_RX_BUF是接收缓冲区,USART_REC_LEN是缓冲区的长度。这里可以看下库中HAL_UARTEx_ReceiveToIdle_IT的定义和提示:

STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号

框1的地方说,这个函数用于在中断模式下接收一定量数据,直到指定的数据长度被接收到或者空闲中断产生。也就是说,如果USART_REC_LEN定义很小,还没到产生空闲中断,接收就会完成。

框2的地方,即是打开串口空闲中断。所以不需要额外再去开启空闲中断了。

2. 中断处理:

中断处理定义在void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)这个中断回调函数中。注意到,和使用DMA传输时是同一个回调函数。

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	u8 len=0;
	u8 data[25];
	u8 uart4_len=0;
	u8 uart4_data[50];
	if(huart->Instance == USART2)
	{
		HAL_UART_DMAStop(huart);
		len = USART_REC_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);// 获取DMA中传输的数据个数
		if (USART2_RX_BUF[0] == 0x0F && len == 25)	//接受完一帧数据
		{
			memcpy(data,USART2_RX_BUF,len);
			update_sbus(data);
		}
		HAL_UARTEx_ReceiveToIdle_DMA(&huart2,USART2_RX_BUF,USART_REC_LEN);		// 再次开启DMA空闲中断
	}
	
	if(huart->Instance == UART4)
	{		
		while (USART4_RX_BUF[uart4_len] != '\0')	uart4_len++;
		memcpy(uart4_data,USART4_RX_BUF,uart4_len);
		HAL_UART_Transmit(&huart4,uart4_data,uart4_len,0xff);
		
		// 调用printf是使用串口1
		printf("data: %s\r\n", uart4_data);	
		printf("data length: %d\r\n", uart4_len);	
		
		memset(USART4_RX_BUF, 0, USART_REC_LEN); 
		memset(uart4_data, 0, sizeof(uart4_data)); 

		HAL_UARTEx_ReceiveToIdle_IT(&huart4,USART4_RX_BUF,USART_REC_LEN);
	}
}	

void USART2_IRQHandler(void)
{
	HAL_UART_IRQHandler(&huart2); //调用HAL库中断处理公用函数
}

void UART4_IRQHandler(void)
{
	HAL_UART_IRQHandler(&huart4); //调用HAL库中断处理公用函数
}

回调函数中就是读取USART4_RX_BUF缓冲区的数据和数据长度,然后做相应处理,这里只是简单的原数据发送回去,如果是SBSU信号或Modbus或其他带协议帧的数据,则可根据帧头帧尾、数据长度、校验位等做进一步处理。

最终实现的效果就是上位机发送什么,单片机返回什么,如图:

STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号

五. 总结

以上三种方式都能实现串口空闲中断接收不定长数据,适合用于处理不定长数据接收、减少CPU负担,相比较而言,方法三不使用DMA,使用上更简洁。方法一、二使用DMA,好处是可以减少CPU负担。文章来源地址https://www.toymoban.com/news/detail-484474.html

到了这里,关于STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32基于HAL库的串口接受中断和空闲中断

    在通信方面。UART由于全双工通信,可以同时接受数据和发送数据而被广泛使用。 而接受数据则又有很多种方法 比如: 1根据结束符判断,数据是字符串形式,所以一般串口接受的接受符就是 \\\"rn\\\"  换成16进制ascil码显示就是 0X0D   0X0A (对应rn)  2定时器中断,设计\\\"喂狗信号量

    2023年04月08日
    浏览(49)
  • STM32F4_HAL库_串口阻塞/中断/DMA三种方式发送数据的配置

    串口阻塞发送的意思就是,发送一段数据,在没有发送完所有数据之前,一直停留在此发送函数(可设定阻塞时间),这个过程中会阻塞别的程序运行; HAL库的配置分为两个层次,一个是HAL库内部调用的、与MCU硬件相关的初始化xxx_MspInit,一个是我们外部调用的初始化xxx_In

    2023年04月25日
    浏览(53)
  • 【STM32+HAL库+CubeMX】UART轮询收发、中断收发、DMA收发方法及空闲中断详解

    Author: DrinkCat(szt@drinkcat.com) Copyright © 2023 DrinkCat Original link: DrinkCat’s Blog UART是一种异步串行通信接口,常用于通过串口与外部设备进行通信。它通过发送和接收数据帧来实现数据传输,使用起来相对简单。UART通常包含发送器(Transmitter)和接收器(Receiver),通过两根信号线

    2024年02月10日
    浏览(40)
  • STM32学习笔记(五)串口空闲中断+DMA实现不定长收发(stm32c8t6)

    记录一下学习过程 DMA DMA,全称为: Direct Memory Access,即直接存储器访问, DMA 传输将数据从一个 地址空间复制到另外一个地址空间。 这一过程无需cpu的参与,从而提高cpu使用的效率 DMA相关的参数:1 数据的源地址、2 数据传输的目标地址 、3 传输宽度,4 传输多少字节,5 传

    2024年02月14日
    浏览(47)
  • stm32串口空闲中断+DMA传输接受不定长数据+letter shell 实现命令行

    空闲中断(IDLE),俗称帧中断,即第一帧数据接收完毕到第二帧数据开始接收期间存在一个空闲状态(每接收一帧数据后空闲标志位置1),检测到此空闲状态后即执行中断程序。 空闲中断的优点在于省去了帧头帧尾的检测 ,进入中断程序即意味着已经接收到一组完整数据,仅需

    2024年02月03日
    浏览(60)
  • STM32—HAL库中断/DMA控制和完成串口通信

    目录 一、解决的问题 二、串口通讯协议和RS-232的介绍以及USB/TTL转232模块的工作原理   1、 串口协议和RS-232标准:  (1)串口协议: (2)RS-232 标准:   2、RS232电平与TTL电平的区别   3、USB/TTL转232“模块(CH340芯片为例)  (1)基本原理:  (2)CH340模块介绍: ​三、搭

    2024年02月02日
    浏览(74)
  • STM32使用三种方式(阻塞、中断、DMA)实现串口发送和接收数据

    记录下学习STM32开发板的心得的和遇见的问题。 板卡型号:STM32F405RGT6 软件:STM32CubeMX、IAR STM32串口外设提供了3种接收和发送方式:阻塞、中断、DMA,主要给大家分享中断方式接收不定长数据和DMA使用空闲中断接收不定长数据。 阻塞发送: 阻塞接收: 两个函数需要注意的就

    2024年02月03日
    浏览(51)
  • 【STM32】CUBEMX之串口:串口三种模式(轮询模式、中断模式、DMA模式)的配置与使用示例 + 串口重定向 + 使用HAL扩展函数实现不定长数据接收

    目录   总览 使用CUBEMX创建工程的基本配置 CUBEMX中的配置 Keil中的配置 实物连接 串口轮询模式 轮询模式HAL库函数 特点 实验一:发送数据给单片机并让其返回相同值 串口重定向 串口中断模式 在CUBEMX中打开串口中断 中断模式HAL库函数 特点 实验二:使用中断回调完成实验一

    2024年04月10日
    浏览(74)
  • (stm32之HAL库)UART工作在DMA模式要打开串口中断吗?

    最近学习了stm32(F4xx)的串口在DMA模式下的使用,期间以ST官方提供的例程进行参考学习,发现其初始化过程中是打开了UART的中断的,而且HAL库中stm32f4xx_hal_uart.c文件中的DMA模式使用说明里也有这么一句话: 即在非循环模式下(也就是发完一次数据就停止的常用模式)需要配置

    2024年02月12日
    浏览(39)
  • HAL库 STM32运用DMA与IDLE中断实现高效串口通信 (附代码)

    最近想做一个控制电机的项目,其中会用到Pytho与单片机STM32之间的互同,最近也在看一些关于数据通信和拆包的相关知识,所以记录一下这段时间里对两者之间的互通所做的事情和发现的问题,以供自己和大家参考。 单片机的串口是我们常用的与电脑通信的外设,本次与P

    2024年01月22日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包