当前位置: 首页 > news >正文

DMA直接内存访问,STM32实现高速数据传输使用配置

1、DMA运用场景

        随着智能化、信息化的不断推进,嵌入式设备的数据处理量也呈现指数级增加,因此对于巨大的数据量处理的情况时,必须采取其它的方式去替CPU减负,以保证嵌入式设备性能。例如SD卡存储器和音视频、网络高速通信等其它情景使用时,如果仅靠CPU去处理,将会消耗大量的系统资源,并且可能不能满足设备实时性的要求,对于嵌入式等一众资源受限的设备中,这是致命的。因此有必要采取一种特殊的方式,使得在执行大量数据处理过程中,CPU依然去执行正常的嵌入式系统任务。

        在嵌入式系统中,常用DMA去解决这一问题。DMA(Direct Memory Access),直接存储器访问)是一种特殊的硬件功能,用于数据传输而不需要CPU的干预DMA主要用于高速数据传输,可以提高系统性能和效率

        ①数据传输:DMA可以在外设和存储器之间进行高速数据传输,例如将数据从外设(如传感器、音频设备、网络接口等)直接传输到存储器中,或者从存储器中直接传输到外设中。这样可以减少CPU的负载,并提高数据传输的速度和效率。

        ②音视频处理:在多媒体应用中,DMA可以用于将音频、视频等数据从外设传输到存储器中进行处理,或者从存储器传输到外设进行播放。通过使用DMA,系统可以实现高质量的音视频数据传输和处理,同时降低对CPU的负担。

        ③存储器处理:DMA可以用于将存储器中的数据备份到外部存储设备(如硬盘、闪存等),或从外部存储设备中恢复数据到存储器中。这样可以提高数据备份和恢复的速度,并降低对CPU的负载。

        ④高速通信:DMA可以用于在嵌入式系统中实现高速通信,例如通过网络接口卡(如以太网)、串行接口(如UART、SPI)等传输数据。DMA可以在数据传输时,绕过CPU直接在外设和存储器之间进行传输,提高数据传输的速度和效率。

2、STM32 DMA基础

在STM32F4xx官方参考手册文档中,有对DMA控制器的讲解说明,内容十分的丰富,在这一部分中将其中较为核心基础的内容进行了梳理。

直接存储器访问 (DMA) 用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。

DMA搬运的三种模式:

①、内存--->内存

②、内存--->外设

③、外设--->内存

DMA1:外设--->内存,内存--->外设

DMA2:外设--->内存,内存--->外设,内存--->内存

DMA2比DMA1多了一个内存到内存的处理功能,因此,如果需要实现内存到内存的DMA搬运模式,必须使用DMA2。

流:是数据传输的一条链路,每个DMA控制器有8条独立的数据流,每次传输的最大数据量为65535,如果数据单位为字的话,可以一次传输256KB。

通道:每个数据流有8个通道选择,每个通道对应不同的DMA请求。

同一个数据流只能使用一个通道,同一个DMA控制器可以使用多个数据流。

仲裁器:仲裁器为两个 AHB 主端口(存储器和外设端口)提供基于请求优先级的 8 个 DMA 数据流请求管理,并启动外设/存储器访问序列。

仲裁器优先级管理分为软件优先级管理和硬件优先级管理。多个数据流到来时,仲裁器会分为两个阶段进行仲裁,第一个阶段为软件优先级管理,在其编程时设置数据流的优先级第二个阶段为硬件阶段,由数据流的硬件编号决定。

FIFO:源和目标之间的一个数据中转站。FIFO模式下,可以将要传输的多个数据(或字节)累计存储在FIFO缓冲器中,然后在FIFO缓冲器中设置存储阈值,当到达阈值时,FIFO会自动把所有存储的数据一次性的发送到目标地址。

一个FIFO为4个字的大小,每个数据流有4字的FIFO,DMA配置为存储器---存储器模式时,FIFO由硬件开启,软件控制无效。且DMA配置为存储器到存储器模式时,不能设置为循环传输。

如图所示可知,DMA1、DMA2控制器挂载在AHB1总线下

由STM32F4xx官方参考手册可知,对于STM32F407系列,其嵌入式SRAM的起始映射的地址0x2000 0000开始。

由STM32F4xx官方参考手册可知,对于STM32F407系列,其嵌入式FLASH的起始映射的地址0x0800 0000开始。

3、STM32 编程实现DMA

在这一部分的讲解梳理中,将DMA配置为了内存--->内存模式,如果是要配置为内存--->外设外设--->内存,修改 DMA结构体的DMA_InitStructure.DMA_DIR参数即可其它参数的配置的思路大致相同。

//STM32F407中const修饰的全局存储到FLASH中
const uint32_t src_const_buf[32] = {0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40,0x41424344,0x45464748,0x494A4B4C,0x4D4E4F50,0x51525354,0x55565758,0x595A5B5C,0x5D5E5F60,0x61626364,0x65666768,0x696A6B6C,0x6D6E6F70,0x71727374,0x75767778,0x797A7B7C,0x7D7E7F80};
uint32_t dst_buf[32] = {0};

因为DMA配置结构体中,需要填入外设/内存的地址信息,所以通过打印数组的内存地址,查看数据的存储位置,以确定外设/内存的地址。由上述STM32F4xx的官方参考手册嵌入式FLASH和SRAM部分说明和打印出来的内存地址可知,const修饰的全局变量被存储于嵌入式FLASH中。

DMA数据传输测试,DMA内存到内存模式代码实现效果如下图所示,通过打印的数据也可确定,DMA高速存储成功且数据无误。

实现DMA存储器到存储器,高速数据传输模式的参考代码Demo如下:

#include "stm32f4xx.h"
#include "stm32f4xx_dma.h"
#include <stdio.h>//const修饰的全局存储到FLASH中
const uint32_t src_const_buf[32] = {0xAAAAAAAA,0xBBBBBBBB,0xCCCCCCCC,0xDDDDDDDD,0xEEEEEEEE,0xFFFFFFFF,0x10000000,0x11111111,0x22222222,0x33333333,0x44444444,0x55555555,0x66666666,0x77777777,0x88888888,0x99999999,0x10000000,0x10000000,0x10000000,0x10000000,0x11111111,0x11111111,0x11111111,0x11111111,0x22222222,0x22222222,0x22222222,0x22222222,0x33333333,0x33333333,0x33333333,0x33333333};
uint32_t dst_buf[32] = {0};void DMA_Config(void);
int8_t buf_cmp(uint32_t *pbuf1, uint32_t *pbuf2, int len);int main(void)
{NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );USART1_Init(115200);printf("starting...\r\n");printf("const addr:%X\r\n", (uint32_t)src_const_buf);printf("addr:%X\r\n", (uint32_t)dst_buf);     DMA_Config();while(DMA_GetCmdStatus(DMA2_Stream0) != DISABLE);    //传输完成后,DMA会进行复位if(buf_cmp((uint32_t *)src_const_buf, dst_buf, 32)==0){printf("DMA传输完成,且数据无误...\r\n");printf("src:\r\n");for(int i = 0; i<32; i++){printf("%0X\t", src_const_buf[i]);}printf("\r\n");printf("dst:\r\n");for(int i = 0; i<32; i++){printf("%0X\t", dst_buf[i]);}printf("\r\n");return 0;}else{printf("DMA数据传输故障...\r\n");    return -1;}}void DMA_Config(void)
{DMA_InitTypeDef DMA_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;volatile uint32_t  Timeout = 10000;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);//内存到内存的传送,使用DMA2DMA_DeInit(DMA2_Stream0);    //初始化DMA的寄存器到复位状态while(DMA_GetCmdStatus(DMA2_Stream0) != DISABLE);    //确保DMA复位完成//配置DMA流DMA_InitStructure.DMA_Channel = DMA_Channel_0;    //启用DMA通道0DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)src_const_buf; //FLASH中的数据地址DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dst_buf;
//SRAM的数据地址DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;    //存储器到存储器模式DMA_InitStructure.DMA_BufferSize = (uint32_t)32;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;    //FLASH地址自增使能DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;            //SRAM地址自增//SRAM地址自增使能DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;DMA_Init(DMA2_Stream0, &DMA_InitStructure);    //DMA初始化DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);DMA_Cmd(DMA2_Stream0, ENABLE);        //DMA使能while(DMA_GetCmdStatus(DMA2_Stream0) != ENABLE && (Timeout-->0));if(Timeout == 0){while(1);}NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}int8_t buf_cmp(uint32_t *pbuf1, uint32_t *pbuf2, int len)
{int cnt = 0;for(int i=0; i<len; i++){if(pbuf1[i] != pbuf2[i]){return -1;}}return 0;
}void DMA2_Stream0_IRQHandler(void)
{    //DMA2通道0数据流传输完成中断 if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) == SET){//清除DMA传输完成中断标志位DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);//在此可根据项目需求增加DMA处理完时的操作}}

相关文章:

DMA直接内存访问,STM32实现高速数据传输使用配置

1、DMA运用场景 随着智能化、信息化的不断推进&#xff0c;嵌入式设备的数据处理量也呈现指数级增加&#xff0c;因此对于巨大的数据量处理的情况时&#xff0c;必须采取其它的方式去替CPU减负&#xff0c;以保证嵌入式设备性能。例如SD卡存储器和音视频、网络高速通信等其它情…...

Web安全研究(六)

文章目录 HideNoSeek: Camouflaging(隐藏) Malicious JavaScript in Benign ASTs文章结构Introjs obfuscationmethodologyExample HideNoSeek: Camouflaging(隐藏) Malicious JavaScript in Benign ASTs CCS 2019 CISPA 恶意软件领域&#xff0c;基于学习的系统已经非常流行&am…...

python3 中try 异常调试 raise 异常抛出

一、什么是异常&#xff1f; 异常即是一个事件&#xff0c;该事件会在程序执行过程中发生&#xff0c;影响了程序的正常执行。 一般情况下&#xff0c;在Python无法正常处理程序时就会发生一个异常。 异常是Python对象&#xff0c;表示一个错误。 当Python脚本发生异常时我…...

Java中的序列化是什么?如何实现对象的序列化和反序列化?请解释Serializable接口的作用是什么?请解释transient关键字的作用是什么?为什么会使用它?

Java中的序列化是指将对象转换为字节序列的过程&#xff0c;以便可以在网络上传输或将其保存到持久存储介质中。反序列化则是将字节序列重新转换回对象的过程。Java提供了一种称为序列化&#xff08;Serialization&#xff09;的机制来实现对象的序列化和反序列化。 要实现对象…...

二维差分---三维差分算法笔记

文章目录 一.二维差分构造差分二维数组二维差分算法状态dp求b[i][j]数组的二维前缀和图解 二.三维前缀和与差分三维前缀和图解:三维差分核心公式图解:模板题 一.二维差分 给定一个原二维数组a[i][j],若要给a[i][j]中以(x1,y1)和(x2,y2)为对角线的子矩阵中每个数都加上一个常数…...

D. Divisible Pairs

思路&#xff1a;我们预处理出每个数分别摸上xy的值&#xff0c;用map存一下&#xff0c;然后遍历每个数&#xff0c;如果a b是x的倍数的话&#xff0c;那么他们模x的值相加为x&#xff0c;如果a - b是y的倍数的话&#xff0c;那么他们的模y的值相等。 代码&#xff1a; voi…...

【教程】Kotlin语言学习笔记(二)——数据类型(持续更新)

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【Kotlin语言学习】系列文章 第一章 《认识Kotlin》 第二章 《数据类型》 文章目录 【Kotlin语言学习】系列文章一、基本数据…...

react 插槽

问题开发当中会经常出现组件十分相似的组件&#xff0c;只有一部分是不同的 解决&#xff1a; 父组件:在引用的时候 import { Component } from "react"; import Me from "../me";const name <div>名称</div> class Shoop extends Compone…...

Linux运用fork函数创建进程

fork函数&#xff1a; 函数原型&#xff1a; pid_t fork(void); 父进程调用fork函数创建一个子进程&#xff0c;子进程的用户区父进程的用户区完全一样&#xff0c;但是内核区不完全一样&#xff1b;如父进程的PID和子进程的PID不一样。 返回值&#xff1a; RETURN VALUEO…...

Pytest测试技巧之Fixture:模块化管理测试数据

在 Pytest 测试中&#xff0c;有效管理测试数据是提高测试质量和可维护性的关键。本文将深入探讨 Pytest 中的 Fixture&#xff0c;特别是如何利用 Fixture 实现测试数据的模块化管理&#xff0c;以提高测试用例的清晰度和可复用性。 什么是Fixture&#xff1f; 在 Pytest 中&a…...

设计模式-职责链模式Chain of Responsibility

职责链模式 一、原理和实现二、实现方式1) 使用链表实现2) 使用数组实现3) 扩展 作用&#xff1a;复用和扩展&#xff0c;在实际的项目开发中比较常用。在框架开发中&#xff0c;我们也可以利用它们来提供框架的扩展点&#xff0c;能够让框架的使用者在不修改框架源码的情况下&…...

书生浦语大模型实战营-课程作业(3)

下载sentence_transformer的代码运行情况。sentence_transformer用于embedding&#xff08;转向量&#xff09; 本地构建持久化向量数据库。就是把txt和md文件抽取出纯文本&#xff0c;分割成定长&#xff08;500&#xff09;后转换成向量&#xff0c;保存到本地&#xff0c;称…...

考研英语单词25

Day 25 bench n.长凳 elastic n.橡皮圈&#xff0c;松紧带 a.灵活的 “e-last 延伸出去” disaster n.灾难&#xff0c;灾祸【disastrous a.灾难性的&#xff0c;极坏的】 deadly a.致命的&#xff0c;极端的&#xff0c;势不两立的 hike n.徒步旅行&…...

计算机网络——08应用层原理

应用层原理 创建一个新的网络 编程 在不同的端系统上运行通过网络基础设施提供的服务&#xff0c;应用进程批次通信如Web Web服务器软件与浏览器软件通信 网络核心中没有应用层软件 网络核心没有应用层功能网络应用只能在端系统上存在 快速网络应用开发和部署 网络应用…...

面试计算机网络框架八股文十问十答第五期

面试计算机网络框架八股文十问十答第五期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01;关注专栏后就能收到持续更新&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1&#xff09;与缓存相关的HTTP请…...

拟合案例1:matlab积分函数拟合详细步骤及源码

本文介绍一下基于matlab实现积分函数拟合的过程。采用的工具是lsqcurvefit和nlinfit两个函数工具。关于包含积分运算的函数,这里可以分为两大类啊。我们用具体的案例来展示:一种是积分运算中不包含这个自变量,如下图的第一个公式,也就是说它这个积分运算只有R和Q这两个待定…...

嵌入式软件设计入门:从零开始学习嵌入式软件设计

&#xff08;本文为简单介绍&#xff0c;个人观点仅供参考&#xff09; 首先,让我们了解一下嵌入式软件的定义。嵌入式软件是指运行在嵌入式系统中的特定用途软件,它通常被用来控制硬件设备、处理实时数据和实现特定功能。与桌面应用程序相比,嵌入式软件需要具备更高的实时性、…...

Educational Codeforces Round 135 (Rated for Div. 2)C. Digital Logarithm(思维)

文章目录 题目链接题意题解代码 题目链接 C. Digital Logarithm 题意 给两个长度位 n n n的数组 a a a、 b b b&#xff0c;一个操作 f f f 定义操作 f f f为&#xff0c; a [ i ] f ( a [ i ] ) a [ i ] a[i]f(a[i])a[i] a[i]f(a[i])a[i]的位数 求最少多少次操作可以使 …...

微信小程序介绍、账号申请、开发者工具目录结构详解及小程序配置

目录 一、微信小程序介绍 1.什么是小程序&#xff1f; 2.小程序可以干什么&#xff1f; 3.微信小程序特点 二、账号申请 1.账号注册 2.测试号申请 三、安装开发工具 四、开发小程序 五、目录结构 JSON 配置 小程序配置 app.json 工具配置 project.config.json 页…...

数字的魅力之情有独钟的素数

情有独钟的素数 什么是素数 素数&#xff08;Prime number&#xff09;也称为质数&#xff0c;是指在非0自然数中&#xff0c;除了1与其本身之外不拥有其他因数的自然数。也就是说&#xff0c;素数需要满足两个条件&#xff1a; 大于1的整数&#xff1b;只拥有1和其自身两个…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言&#xff1a;我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM&#xff08;Java Virtual Machine&#xff09;让"一次编写&#xff0c;到处运行"成为可能。这个软件层面的虚拟化让我着迷&#xff0c;但直到后来接触VMware和Doc…...

人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型

在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重&#xff0c;适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解&#xff0c;并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...