STM32 CubeMX配置串口DMA收发,使用串口空闲中断方式

首先感谢网上的小伙伴,这篇文章记录下浏览量过6W,再学习道路上继续努力加油!小编调试串口功能发现普通方式非常暂用时间,在此记录一下串口DMA方式加串口空闲中断方式收发数据;

1、cubemx配置:串口1的DMA方式,修改中断优先级,串口DMA发送一次不需要循环发送,串口宽度Byte;

 

二、源码:

 

 

文件main.c中:

/* USER CODE BEGIN Includes */

#include <stdio.h>						//uart redirect fputc
#include <string.h>						//copy function
#include <stdarg.h>						//va_start /vsnprintf /va_end function

/* USER CODE END Includes */


/* USER CODE BEGIN 0 */

#define	ON	1
#define	OFF	0
#define	UART_DEBUG	&huart1			//调试串口
#define	BUFFER_SIZE	256					//串口DMA发送接收数组大小
typedef	union
{
	unsigned int interface;
	struct
	{	
		uint8_t rx_buffer[BUFFER_SIZE];  	 	//接收数据数组
		uint8_t tx_buffer[BUFFER_SIZE];  	 	//发送数据数组
		uint8_t uart_buffer[BUFFER_SIZE];  	//接收数据缓存数组
		uint8_t recive_count;							 	//接收计数
		unsigned char interrupt_idle	:1;		//空闲中断标志
		
	}bits;
}UART_MDADAT;

UART_MDADAT	uartDMA_data;


/******************************************************************************************
*** 函数名称: Debug_Printf
*** 输入参数: 无
*** 返 回 值: 无
*** 说    明:串口1中断回调函数
*** 功能说明:
***	编者										时间										版本
***	WL											2020/12/17						 V0.1
******************************************************************************************/
void user_uart1IT_ReceiveCallback(void)
{
	uint8_t temp;
	if((__HAL_UART_GET_FLAG(UART_DEBUG, UART_FLAG_IDLE) != RESET))  //获取IDLE标志位,idle标志被置位
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);														//清除空闲中断标志位
		HAL_UART_DMAStop(UART_DEBUG);																	//停止串口DMA功能
		
		temp = huart1.hdmarx->Instance->CNDTR;												//得到当前还剩余多少个数据 
		uartDMA_data.bits.recive_count = BUFFER_SIZE - temp;					//接收数据计数
		
		uartDMA_data.bits.interrupt_idle = ON;												// 接受完成标志位置1	
		
	}
}


/******************************************************************************************
*** 函数名称: Debug_Printf
*** 输入参数: 无
*** 返 回 值: 无
*** 说    明:自定义串口 printf功能
*** 功能说明:
1、sizeof返回定义arr数组时,编译器为其分配的数组空间大小,不关心里面存了多少数据。
2、strlen只关心存储的数据内容,不关心空间的大小和类型。
3、串口DMA方式打印的数组需要保留,DMA直接操作的是内存,如果DMA未打印完成就清空数组会出现数据打印不完整的情况

***	编者										时间										版本
***	WL											2020/12/8								V0.1
******************************************************************************************/
void Debug_Printf(UART_HandleTypeDef *huart, char *format, ...)
{
	va_list ap;
	
	va_start(ap, format);																			//初始化 ap 变量
	vsnprintf((char *)uartDMA_data.bits.tx_buffer, sizeof(uartDMA_data.bits.tx_buffer), format, ap);		//可变参数。用于向字符串中打印数据、数据格式用户自定义
	va_end(ap);																								//允许使用了 va_start 宏的带有可变参数的函数返回
	
	HAL_UART_Transmit_DMA(UART_DEBUG, (uint8_t *)uartDMA_data.bits.tx_buffer, strlen((char *)uartDMA_data.bits.tx_buffer));	//打印数据
	
}


/* USER CODE END 0 */


int main(void)
{
    //中间配置省略。。。。。。。

  /* USER CODE BEGIN 2 */

	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
	HAL_UART_Receive_DMA(&huart1, uartDMA_data.bits.rx_buffer, BUFFER_SIZE);
	
  /* USER CODE END 2 */


  while (1)
  {
	
		
		if(uartDMA_data.bits.interrupt_idle == ON)		//有空闲中断
		{
			uartDMA_data.bits.interrupt_idle = OFF;
			
			memset(uartDMA_data.bits.uart_buffer, 0, sizeof(uartDMA_data.bits.uart_buffer));																						//清除缓存数据数组
			memcpy(uartDMA_data.bits.uart_buffer, uartDMA_data.bits.rx_buffer, strlen((char *)uartDMA_data.bits.rx_buffer));						//取出数据
			memset(uartDMA_data.bits.rx_buffer, 0, sizeof(uartDMA_data.bits.rx_buffer));																								//清空数组
			HAL_UART_Receive_DMA(UART_DEBUG, uartDMA_data.bits.rx_buffer, sizeof(uartDMA_data.bits.rx_buffer));													//重新启动串口DMA功能
			
			Debug_Printf(UART_DEBUG, "\r\n*******************************串口 DMA方式接收打印如下 *****************************\r\n "); 	HAL_Delay(100);
			
			Debug_Printf(UART_DEBUG, "\r\n HAL_UART_Transmit_DMA 库函数打印\t:"); 	HAL_Delay(100);
			HAL_UART_Transmit_DMA(UART_DEBUG, (uint8_t *)uartDMA_data.bits.uart_buffer, strlen((char *)uartDMA_data.bits.uart_buffer));	//打印接收到的数据
			HAL_Delay(100);
			Debug_Printf(UART_DEBUG, "\r\nDebug_Printf函数打印数组\t\t:"); 					HAL_Delay(100);
			Debug_Printf(UART_DEBUG, (char *)uartDMA_data.bits.uart_buffer);	
			HAL_Delay(100);
			Debug_Printf(UART_DEBUG, "\r\nDebug_Printf函数打印字符\t\t:"); 					HAL_Delay(100);
			Debug_Printf(UART_DEBUG, "uart MDA Debug printf function");
			HAL_Delay(100);
			Debug_Printf(UART_DEBUG, "\r\nDebug_Printf函数打印串口接收计数值\t:"); 					HAL_Delay(100);
			Debug_Printf(UART_DEBUG, "recive_count: %d\r\n", uartDMA_data.bits.recive_count);
			
		}
		
		
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
}

stm32f1xx_it.c代码:


void USART1_IRQHandler(void)
{
    //省略。。。。。
	user_uart1IT_ReceiveCallback();
	
}

三、功能验证:

 

 

 

链接:https://pan.baidu.com/s/1Byt51Ux7JX_snSXXf6PJEQ 
提取码:k3xf 
 

 

 

 

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
使用STM32DMA方式进行串口数据收发时,可以使用空闲中断来判断数据接收完成。具体步骤如下: 1. 配置串口DMA模式,设置DMA通道和缓存地址等参数。 2. 启动DMA传输,使其开始接收数据。 3. 在空闲中断中判断DMA传输是否完成,可以通过检查DMA传输的剩余数据长度来判断。如果剩余数据长度为0,则说明数据传输完成。 4. 在空闲中断中处理接收到的数据,例如将数据存储到缓存中等操作。 5. 处理完接收到的数据后,重新配置DMA通道和缓存地址等参数,使其可以继续接收数据。 下面是一个简单的示例代码: ```c void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // 检查DMA传输是否完成 if (__HAL_DMA_GET_COUNTER(huart->hdmarx) == 0) { // 处理接收到的数据 // ... // 重新配置DMA通道和缓存地址等参数 HAL_UART_Receive_DMA(huart, rx_buffer, BUFFER_SIZE); } } int main() { // 初始化串口DMA通道等参数 HAL_UART_Receive_DMA(&huart, rx_buffer, BUFFER_SIZE); // 启用空闲中断 __HAL_UART_ENABLE_IT(&huart, UART_IT_IDLE); while (1) { // 主循环 // ... } } ``` 在以上示例代码中,我们先使用HAL_UART_Receive_DMA函数启动DMA传输,并在空闲中断中检查DMA传输是否完成。如果传输完成,则处理接收到的数据,并重新配置DMA通道和缓存地址等参数,使其可以继续接收数据。同时,我们也启用了空闲中断,以便能够及时检测到数据传输的完成。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值