STM32 F4串口空闲中断 + DMA实现数据发送

这篇具有很好参考价值的文章主要介绍了STM32 F4串口空闲中断 + DMA实现数据发送。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

最近在做 STM32 + ROS车的项目,STM32与ROS之间通信由于数据量大,所以在 STM32端 使用 空闲中断 + DMA 的方案来减轻 CPU 的压力。

文章目录

一、空闲中断

空闲中断顾名思义为空了,闲了,没事了进的中断,在没有数据流的时候会进入进行读取。
在我们串口进行发送时实则为连续发送,两个字节之间时间间隔非常小,这时串口接收中断未达到空闲的状态,当一组数据发送完成后会进行一系列运行后再次发送,这段时间内没有数据再次接收,这时会进入空闲中断。
这个间隔怎么定义呢?在空闲总线上,空闲的定义是:总线上在一个字节的时间内没有再接收到数据。
综上所诉:空闲中断在总线上没有信息的时候会进入中断,集中处理在这一段时间接收到的数据。在有数据的时候不会进入中断。
优点:通常使用的 USART_IT_RXNE接收中断配置再有数据进入时就会切换到串口进行处理,每次处理一个字节。频繁的进入中断,大量的占用CPU带宽来进行处理,使用空闲中断USART_IT_IDLE后,在接收数据时不进入中断,在接收完一组数据时,进入中断,同时处理这一组数据,大大节省了时间,降低了CPU占用时间,提高了整体性能。代码与正常串口配置大致无异,在最后中断配置处将接收中断修改为空闲中断即可。之后代码中会列出。

二、DMA

DMA 简介:
直接存储器访问 (DMA) 用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。
DMA分为DMA1与DMA2,
DMA1有两种模式,分为:
1、外设->存储器
2、存储器->外设
DMA2有三种模式,分为:
1、外设->存储器
2、存储器->外设
3、存储器到存储器
之所以有差异在于DMA1控制器AHB外设端口不连接到中线矩阵,因此,仅 DMA2 数据流能够执行存储器到 存储器的传输。
FIFO介绍:
DMA接收有两种模式,一种为直接模式,另一种为FIFO模式
FIFO为缓存区,大小为32位(16个字节,8个半字,4个字),独立的源和目标传输宽度(字节、半字、字),在单位上分为三种读取FIFO的方式,为(字节、半字、字)每个数据流都有一个独立的 4 字 FIFO,阈值级别可由软件配置为 1/4、1/2、3/4 或满。

三、代码部分

1、串口配置

使用正常的串口配置即可

/*******************************************************************************
* Function Name  : USART2_Configuration
* Description    : 串口二配置
*******************************************************************************/
void USART2_Configuration(void)
{
	
	GPIO_InitTypeDef GPIO_InitStructure;                                          //定义GPIO初始化结构体
	USART_InitTypeDef USART_InitStructure;                                         //定义USART初始化结构体
	/*时钟配置不需要配置AFIO 只要配置为复用功能即可*/
//	GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2); // tx
//	GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2); // rx
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); // tx
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); // rx
														  
//	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5 | GPIO_Pin_6;                          //设置初始化GPIO为PIN5、PIN6
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2 | GPIO_Pin_3;                          //设置初始化GPIO为PIN5、PIN6
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;                              //设置GPIO的速度为100MHz
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;                                    //设置GPIO模式为复用模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;								  //设置GPIO输出类型为推挽输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;						          //设置GPIO为连接上拉
//	GPIO_Init(GPIOD,&GPIO_InitStructure);                                         //初始化
	GPIO_Init(GPIOA,&GPIO_InitStructure);                                         //初始化

    USART_InitStructure.USART_BaudRate=115200;                                    //设置USART的波特率为115200
    USART_InitStructure.USART_Parity=USART_Parity_No;                             //设置USART的校验位为None
    USART_InitStructure.USART_WordLength=USART_WordLength_8b;                     //设置USART的数据位为8bit
    USART_InitStructure.USART_StopBits=USART_StopBits_1;                          //设置USART的停止位为1
    USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //失能硬件流控制
    USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;                   //设置USART的模式为发送接收模式
  	USART_Init(USART2, &USART_InitStructure);	
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); 									//开启接收中断		若要使用 DMA 在 DMA 接收中有关闭中断,开启空闲中断
 	USART_Cmd(USART2, ENABLE);
}
2、DMA配置

DMA配置时,使用串口的空闲中断,将之前的接收中断失能,使能串口的空闲中断

宏定义:

/* 发送与接收缓存数组 */
#define UART2_DMA_Rx_LEN 100					/* 接收DMA缓存长度配置 */
#define UART2_DMA_Tx_LEN 100					/* 发送DMA缓存长度配置 */
uint8_t UART2_DMA_Rx_Buff[UART2_DMA_Rx_LEN];
uint8_t UART2_DMA_Tx_Buff[UART2_DMA_Tx_LEN];

配置DMA代码:

/*******************************************************************************
* Function Name  : USART2_DMA_RX_Confige
* Description    : 串口二 DMA 接收配置
*******************************************************************************/
void USART2_DMA_RX_Confige(void)
{
	/* 定义DMA初始化结构体 */
	DMA_InitTypeDef  DMA_InitStructure;
	
	DMA_DeInit(DMA1_Stream5);												//复位DMA状态  清空数据
	while(DMA_GetCmdStatus(DMA1_Stream5) != 0)								//判断流内数据是否清零
	{
		printf("DMA1_Stream5 != 0\r\n");
	}
	
	DMA_InitStructure.DMA_Channel = DMA_Channel_4;							//DMA通道配置
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);		//DMA外设基地址					源数据地址
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)UART2_DMA_Rx_Buff;	//DMA内存基地址					目标地址
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;					//DMA数据传输方向				外设->内存 外设为源,内存为目的区
	DMA_InitStructure.DMA_BufferSize = UART2_DMA_Rx_LEN;					//DMA通道的缓存的大小			数据数目
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;		//设置DMA的外设递增模式			外设地址寄存器不递增
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;					//设置DMA的内存递增模式			内存地址寄存器递增
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;	//外设数据字大小(32位),数据宽度为8位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;			//内存数据字大小(32位),数据宽度为8位
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;							//正常工作模式					一次传输模式
	DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;					//设置DMA数据流优先级			优先级为最高
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;					//禁用FIFO模式
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;			//指定了FIFO阈值水平			禁用FIFO模式
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;				//指定的Burst转移配置内存传输	单次模式
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;		//指定的Burst转移配置外围转移	单次模式
	DMA_Init(DMA1_Stream5, &DMA_InitStructure);								//配置DMA1的通道 流5
	
	//中断配置
	USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);	//关闭串口接受中断
	USART_ITConfig(USART2,USART_IT_IDLE,ENABLE);	//开启串口空闲中断
	
	/* 开启DMA接收 */
	DMA_Cmd(DMA1_Stream5,ENABLE);							//使能DMA接收通道
	USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);			//采用DMA方式接收
}

配置中断接收代码

uint8_t buf[UART2_DMA_Rx_LEN];
int FlagSize;
void USART2_IRQHandler(void)
{
    //接收完成中断处理
    if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
    {
		USART2->SR;
		USART2->DR; //清USART_IT_IDLE标志	不进行此步骤会一直进中断

		/*************************************** 开始接收准备 *****************************************/
		DMA_Cmd(DMA1_Stream5,DISABLE);					/* 关闭DMA */
		DMA_ClearFlag(DMA1_Stream5,DMA_FLAG_TCIF5);		/* 清除标志位 */
		
		/***************************************** 接收算法 ******************************************/
//		UsartReceive(&ReceiveROS);
		FlagSize = UART2_DMA_Rx_LEN - DMA_GetCurrDataCounter(DMA1_Stream5);					/* 获得接收帧帧长 */
		memset(buf,0x0,UART2_DMA_Rx_LEN);											/* 对接收buff进行清零 */
		memcpy(buf,UART2_DMA_Rx_Buff,FlagSize);										/* 数据接收 */	
		/************************************* 开始下一帧接收准备 *************************************/
		USART_ClearFlag(USART_Receive, USART_FLAG_IDLE);                              		/* 清除标志位 */
		//设置传输数据长度
		DMA_SetCurrDataCounter(DMA1_Stream5,UART2_DMA_Rx_LEN);
		//打开DMA
		DMA_Cmd(DMA1_Stream5,ENABLE);
    }
}

测试时可以使用串口助手给串口二发送数据看是否能够成功接收。

以上代码备注都很清晰完善,我就不过多赘述,感谢观看!!!文章来源地址https://www.toymoban.com/news/detail-597396.html

到了这里,关于STM32 F4串口空闲中断 + DMA实现数据发送的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • STM32使用串口空闲中断(IDLE)和 DMA接收一串数据流

    STM32使用串口空闲中断(IDLE)和 DMA接收一串数据流

    方法一、使用宏定义判断IDLE标志位 空闲的定义是总线上在一个字节的时间内没有再接收到数据,USART_IT_IDLE空闲中断是检测到有数据被接收后,总线上在一个字节的时间内没有再接收到数据的时候发生的。 串口空闲中断(UART_IT_IDLE):STM32的IDLE的中断在串口无数据接收的情况

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

    STM32学习笔记(五)串口空闲中断+DMA实现不定长收发(stm32c8t6)

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

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

    STM32使用三种方式(阻塞、中断、DMA)实现串口发送和接收数据

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

    2024年02月03日
    浏览(11)
  • GD32实现串口空闲(IDLE)中断 + DMA机制接收数据

    GD32实现串口空闲(IDLE)中断 + DMA机制接收数据

    前言 串口功能在单片机开发中,是比较常用的外设,熟练使用串口功能也是驱动开发必备的技能之一。 DMA 是一种CPU辅助手段,可以在CPU不参与的情况下,是做一些辅助CPU的事情,如通常的数据搬运。 在没有DMA之前,数据读取时,需要CPU的处理,在多任务处理时,增加资源紧

    2023年04月13日
    浏览(8)
  • STM32 cubemx+串口空闲中断+DMA双缓冲

            写这篇文章是为了记录下之前做过的项目中用到的一部分关键技术,之前做过的项目中涉及到 采用最小开销来实时接收遥控器数据、能够准确验证传输过来数据的准确性 ,减小误差率,要求能稳定适用于不同的环境。 目录 1、为什么要用到串口空闲中断? 2、为

    2024年02月09日
    浏览(11)
  • STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号

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

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

    2024年02月09日
    浏览(12)
  • Stm32407串口1空闲中断+DMA收发(基于标准库实现)

    Stm32407串口1空闲中断+DMA收发(基于标准库实现)

    stm32串口的配置很简单,这里就不赘述了,使用 USART_SendData() 阻塞模式发送数据,或是接收中断配置 “接收缓冲区非空” USART_IT_RXNE ,这种做法效率很低,而且来一个数据中断一次数据处理起来也麻烦。 这里基于STM32F407提供一种串口空闲中断+DMA接收的方式,通过库函数编程

    2024年02月16日
    浏览(9)
  • STM32 cubemx配置DMA+空闲中断接收不定长数据

    STM32 cubemx配置DMA+空闲中断接收不定长数据

    本篇文章给大家讲解一下DMA+串口空闲中断接收串口不定长数据,之前我们也是讲解过串口接收不定长数据的,那么本篇文章的话将使用DMA来接收不定长数据。 串口空闲中断是指在串口接收到数据后,在数据的传输结束之后,在一段连续的空闲时间内没有接收到新数据时触发

    2024年02月19日
    浏览(10)
  • STM32_串口中断接收数据_空闲中断

    引言: 1、串口中断接收数据首先要保证完整性(设置串口中断优先级) 2、串口中断接收数据要保证实时性(打开串口空闲中断——空闲时间是2个字节的时间) 3、串口中断接收+DMA缓存,等到需要处理时候在进行处理数据 方法一:直接利用stm32的RXNE和IDLE中断进行接收不定字

    2024年02月13日
    浏览(11)
  • GD32F103串口DMA收发(空闲中断 + DMA)

    GD32F103串口DMA收发(空闲中断 + DMA) 代码如下:

    2024年02月12日
    浏览(8)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包