嵌入式学习(18)-stm32F407串口接收空闲中断+DMA

一、概述

在一些一次性接收大批量数据的引用场合,如果使用接收中断会频繁的进入接收中断影响代码的运行效率。为了解决这个问题可以使用串口的空闲中断+DMA实现。

二、应用

在网上招了一些例程在STM32F407的平台上都没有跑通会出现各种异常,主要原因还是库的版本有更新可能和当前的工程不匹配,经过几天的煎熬终于调通了流程。

三、代码实现

1、初始化程序

void USART3_Init(uint32_t baudrate)
{
    /* IO 及 时钟配置 */
    USART3_TX_GPIO_CLK_ENABLE(); /* 使能 串口TX脚 时钟 */
    USART3_RX_GPIO_CLK_ENABLE(); /* 使能 串口RX脚 时钟 */
    USART3_CLK_ENABLE();      /* 使能 串口 时钟 */
    GPIO_InitTypeDef gpio_init_struct;
    gpio_init_struct.Pin = USART3_TX_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_AF_PP;
    gpio_init_struct.Pull = GPIO_PULLUP;
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
    gpio_init_struct.Alternate = USART3_TX_GPIO_AF;              /* 复用为串口 */
    HAL_GPIO_Init(USART3_TX_GPIO_PORT, &gpio_init_struct); /* 串口TX 脚 模式设置 */
	//
    gpio_init_struct.Pin = USART3_RX_GPIO_PIN;
    gpio_init_struct.Alternate = USART3_RX_GPIO_AF;              /* 复用为USART3 */
    HAL_GPIO_Init(USART3_RX_GPIO_PORT, &gpio_init_struct); /* 串口RX 脚  */
	
	
    /* USART 初始化设置 */
    USART3_handler.Instance = USART3;                  /* 选择串口屏对应的串口 */
    USART3_handler.Init.BaudRate = baudrate;               /* 波特率 */
    USART3_handler.Init.WordLength = UART_WORDLENGTH_8B;   /* 字长为8位数据格式 */
    USART3_handler.Init.StopBits = UART_STOPBITS_1;        /* 一个停止位 */
    USART3_handler.Init.Parity = UART_PARITY_NONE;         /* 无奇偶校验位 */
    USART3_handler.Init.HwFlowCtl = UART_HWCONTROL_NONE;   /* 无硬件流控 */
    USART3_handler.Init.Mode = UART_MODE_TX_RX;            /* 收发模式 */
    HAL_UART_Init( &USART3_handler);                       /* 使能对应的串口, 但会调用MSp */
//    __HAL_UART_DISABLE_IT( &USART3_handler, UART_IT_TC);
    __HAL_UART_ENABLE_IT( &USART3_handler, UART_IT_RXNE);  /* 开启接收中断 */
	__HAL_UART_ENABLE_IT(&USART3_handler, UART_IT_IDLE);    // 使能串口接收空闲中断
	

    HAL_NVIC_SetPriority(USART3_IRQn, 3, 3);              /* 抢占优先级3,子优先级3 */
    HAL_NVIC_EnableIRQ(USART3_IRQn);                      /* 使能USART1中断 */	
	
	
	__HAL_RCC_DMA1_CLK_ENABLE();// 低优先级
//    __HAL_LINKDMA(&USART3_handler, hdmatx, g_dma_handle);   /* 将DMA与USART3联系起来(发送DMA) */	 
__HAL_LINKDMA(&USART3_handler, hdmarx, g_dma_handle); 
    g_dma_handle.Instance = DMA1_Stream1;                    /* 数据流选择 */
    g_dma_handle.Init.Channel = DMA_CHANNEL_4;                               /* DMA通道选择 */
    g_dma_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;           /* 外设到存储器 */
    g_dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;               /* 外设非增量模式 */
    g_dma_handle.Init.MemInc = DMA_MINC_ENABLE;                   /* 存储器增量模式 */
    g_dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;  /* 外设数据长度:8位 */
    g_dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;     /* 存储器数据长度:8位 */
    g_dma_handle.Init.Mode = DMA_NORMAL;                          /* 外设流控模式 */
    g_dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM;             /* 中等优先级 */
	
    g_dma_handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;            /* 关闭FIFO模式 */
    g_dma_handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;    /* FIFO阈值配置 */
    g_dma_handle.Init.MemBurst = DMA_MBURST_SINGLE;               /* 存储器突发单次传输 */
    g_dma_handle.Init.PeriphBurst = DMA_PBURST_SINGLE;            /* 外设突发单次传输 */	
//	  
	HAL_DMA_Init(&g_dma_handle);                          // 将DMA与USART3联系起来(接收DMA)

	HAL_UART_Receive_DMA(&USART3_handler, g_rcvDataBuf, MAX_BUF_SIZE);             // 开启DMA接收
	HAL_DMA_Start(&g_dma_handle,(uint32_t)&USART3->DR,(uint32_t)&g_rcvDataBuf,MAX_BUF_SIZE);
	

}

2、中断处理

void USART3_IRQHandler(void)
{
//     printf("t");
    uint8_t res;
	uint16_t PACKET_DATA_LEN;
	uint16_t t;
    __HAL_UNLOCK( &USART3_handler);

//    if ((__HAL_UART_GET_FLAG( &USART3_handler, UART_FLAG_RXNE) != RESET)) /* 接收到数据 */
//    {
//        HAL_UART_Receive( &USART3_handler, &res, 1, 1000);
        Buffer_Push( &RF_Buffer, res); //接收数据,
//        		printf("%c",res);
//    }	
	if (__HAL_UART_GET_FLAG(&USART3_handler, UART_FLAG_IDLE) != RESET)                 // 获取接收IDLE标志位是否被置位
	{   
       printf("进入空闲中断 !\r\n");          
		__HAL_UART_CLEAR_IDLEFLAG(&USART3_handler); 
//		HAL_UART_DMAStop(&USART3_handler); 	  /* 异常 */	
		HAL_DMA_Abort(&g_dma_handle);
		PACKET_DATA_LEN = (MAX_BUF_SIZE - __HAL_DMA_GET_COUNTER(&g_dma_handle));
         t=__HAL_DMA_GET_COUNTER(&g_dma_handle);	
		printf("使用存储空间:%d 剩余存储空间:%d\r\n",PACKET_DATA_LEN,t);
		printf("接收到的数据:%s",g_rcvDataBuf);

		HAL_UART_Receive_DMA(&USART3_handler, (uint8_t *)g_rcvDataBuf, MAX_BUF_SIZE);  
		HAL_DMA_Start(&g_dma_handle,(uint32_t)&USART3->DR,(uint32_t)&g_rcvDataBuf,MAX_BUF_SIZE);
		// 重新开启DMA传输
		memset(g_rcvDataBuf, 0, sizeof(g_rcvDataBuf));
	}
	
	
	
	
	
	
	
}

3、测试结果

4、源码链接

STM32F407基于串口空闲中断和DMA的实现可以实现大批量数据的接收资源-CSDN文库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/937015.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024.12.15CISCN长城杯铁人三项赛

WEB Safe_Proxy 刚开始比赛看到题目名字里面有Proxy 就先来做这个了(在最近的比赛中见到的proxy题比较多) 题目进入之后给了源码 源码 from flask import Flask, request, render_template_string import socket import threading import htmlapp Flask(__name__)app.rout…

【Linux服务器nginx前端部署详解】ubantu22.04,前端Vue项目dist打包

本文主要讲一下在Linux系统环境下(以ubantu22.04为例),如何用nginx部署前端Vue项目打包的dist静态资源。有些具体的命令就不展开讲了,可以自行查看其他博主的文章,我主要讲整体的步骤和思路。 一、ubantu系统安装ngin…

SAP软件如何启用反记账功能

SAP软件和国内ERP软件不一样,它在录入会计凭证时是不可以录入负数的(即红冲凭证),因此无法直接实现传统意义上的红字冲销。 比如,如下SAP正常和冲销业务产生会计凭证如下: 正常的业务凭证: 借…

iOS swift开发系列 -- tabbar问题总结

1.单视图如何改为tabbar,以便显示2个标签页 右上角➕,输入tabbar 找到控件,然后选中,把entrypoint移动到tabbar控件 2.改成tabbar,生成两个item,配置各自视图后,启动发现报错 Thread 1: “-[p…

Level DB --- coding

Util coding是Level DB中重要的数据结构,它主要用来将uint32,和uint64高效的序列化到字符串中和从字符串中反序列化出来。 coding两种序列化形式 Util coding中主要提供两种序列化形式,即Fixed形式和Var形式。其中Fixed形式是常规形式&…

EfficientNet与复合缩放理论(Compound Scaling Theory) 详解(MATLAB)

1.EfficientNet网络与模型复合缩放 1.1 EfficientNet网络简介 1.1.1 提出背景、动机与过程 EfficientNet是一种高效的卷积神经网络(CNN),由Google的研究团队Tan等人在2019年提出。EfficientNet的设计目标是提高网络的性能,同时减…

CentOS7 Apache安装踩坑

Gnome桌面右键弹出终端。 [rootlocalhost ~]# yum repolist 已加载插件:fastestmirror, langpacks /var/run/yum.pid 已被锁定,PID 为 2611 的另一个程序正在运行。 Another app is currently holding the yum lock; waiting for it to exit... [root…

接收文件并保存在本地

接受多个文件 前端 <input typefile namefilelist> <input typefile namefilelist> <input typefile namefilelist> ... 后端 filelist request.files.getlist(name属性值) 获取文件内容 单个文件 file request.files.get(file)content file.read…

关于解决VScode中python解释器中的库Not Found的问题

关于解决VScode中python解释器中的库Not Found的问题 背景介绍解决步骤1. 检查当前使用的Python解释器2. 确保选择正确的Python解释器3. 安装库到指定的Python环境①使用 pip 完整路径指定&#xff1a;②使用 conda 安装&#xff1a;③使用 python -m pip 指定解释器&#xff1…

springboot436校园招聘系统(论文+源码)_kaic

摘 要 使用旧方法对校园招聘系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在校园招聘系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发的校园招聘系…

YOLOv9改进,YOLOv9引入DLKA-Attention可变形大核注意力,WACV2024,二次创新RepNCSPELAN4结构

摘要 作者引入了一种称为可变形大核注意力 (D-LKA Attention) 的新方法来增强医学图像分割。这种方法使用大型卷积内核有效地捕获体积上下文,避免了过多的计算需求。D-LKA Attention 还受益于可变形卷积,以适应不同的数据模式。 理论介绍 大核卷积(Large Kernel Convolu…

LRM-典型 Transformer 在视觉领域的应用,单个图像生成3D图像

https://yiconghong.me/LRM. 一、Abstract 第一个大型重建模型&#xff08;LRM&#xff09;&#xff0c;它可以在5秒内从单个输入图像预测物体的3D模型。LRM采用了高度可扩展的基于transformer的架构&#xff0c;具有5亿个可学习参数&#xff0c;可以直接从输入图像中预测神经…

鸿蒙开发:一个轻盈的上拉下拉刷新组件

前言 老早之前开源了一个刷新组件&#xff0c;提供了很多常见的功能&#xff0c;也封装了List&#xff0c;Grid&#xff0c;WaterFlow&#xff0c;虽然功能多&#xff0c;但也冗余比较多&#xff0c;随着时间的前去&#xff0c;暴露的问题就慢慢增多&#xff0c;虽然我也提供了…

ByteCTF2024

wp参考&#xff1a; 2024 ByteCTF wp 2024 ByteCTF WP- Nepnep ByteCTF 2024 writeup by Arr3stY0u 五冠王&#xff01;ByteCTF 2024 初赛WriteUp By W&M ByteCTF 2024 By W&M - W&M Team ByteCTF Re WP - 吾爱破解 - 52pojie.cn 2024 ByteCTF - BediveRe_R…

Node.js教程入门第一课:环境安装

对于一个程序员来说&#xff0c;每学习一个新东西的时候&#xff0c;第一步基本上都是先进行环境的搭建&#xff01; 从本章节开始让我们开始探索Node.js的世界吧! 什么是Node.js? 那么什么是Node.js呢&#xff1f;简单的说Node.js 就是运行在服务端的 JavaScript JavaScript…

弧形导轨的变形因素有哪些?

随着弧形导轨的应用日渐普遍&#xff0c;在日常使用中总会遇到很多各种各样的问题&#xff0c;其中变形是最常见的问题&#xff0c;但通过采取正确的预防和解决措施&#xff0c;可以避免其对设备性能和精度造成的影响&#xff0c;以下是一些主要的变形原因&#xff1a; 1、负载…

SSL证书部署(linux-nginx)

一、SSL证书的作用 HTTP协议无法加密数据,数据传输可能产生泄露、篡改或钓鱼攻击等问题。 SSL证书部署到Web服务器后,可帮助Web服务器和网站间建立可信的HTTPS协议加密链接,为网站安全加锁,保证数据安全传输。 二、前提条件 1.已通过数字证书管理服务控制台签发证书。 …

MATLAB引用矩阵元素的几种方法

引用矩阵元素可以通过索引&#xff0c;也可以通过逻辑值 索引 通过引用元素在矩阵中的位置来提取元素&#xff0c;例如&#xff1a; - 逻辑值 通过某种逻辑运算来使得要提取的值变为逻辑 1 1 1&#xff0c;用 A ( ) A() A()提取即可&#xff0c; A A A为原矩阵的名称。 例如&…

一些浅显易懂的IP小定义

IP归属地&#xff08;也叫IP地址&#xff0c;IP属地&#xff09; 互联网协议地址&#xff0c;每个设备上的唯一的网络身份证明。用于确保网络数据能够精准传送到你的设备上。 基于IP数据云全球IP归属地解析&#xff0c;示例Python代码 curl -X POST https://route.showapi.co…

Jupyter Notebook 切换虚拟环境

方法 切换到需要添加到Jupyter Notebook中的虚拟环境&#xff0c;执行&#xff1a; python -m ipykernel install --name Jupyter Notebook中显示的虚拟环境名称如果遇到 [Errno 13] Permission denied: /usr/local/share/jupyter类似的权限问题&#xff0c;可能是没有对应的…