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

STM32—DMA直接存储器访问详解

DMA——直接存储器访问

DMA:Data Memory Access, 直接存储器访问。

DMA和我们之前学过的串口、GPIO都是类似的,都是STM32中的一个外设。串口是用来发送通信数据的,而DMA则是用来把数据从一个地方搬到另一个地方,而且不占用CPU。

举个例子:

我们如果要把一串数据发送给串口 ,CPU先要把这一串数据先一个一个取回来暂存在CPU中的寄存器中,然后再一个一个发送给串口。

这样就会导致CPU不能做其他事情,CPU一直处于被占用的状态。

当DMA出现后,CPU只需要给DMA发送一条命令,如将数据发送给串口,然后DMA就来完成这个上述需要CPU完成的工作了。这就节省了CPU的资源来完成其他操作。


上面我们解释完DMA是什么后,我们接着来看DMA具体有几种方式。

1.P->M(外设到存储器)

后面的ADC数据采集使用的是这一类

2.M->P(存储器到外设)

之前的串口发送实验属于这一类

3.M->M(存储器到存储器)

存储器到存储器的实验一会儿在后面讲

我们先来看一下DMA的功能框图

DMA功能框图讲解

请添加图片描述

我们先把DMA的功能框图分为三大主要部分来讲解:1.DMA请求。2.通道。3.仲裁器

DMA请求

通过上面的DMA框图我们可以看到,DMA请求通常是由外设发起的,例如串口、GPIO、ADC等等。

那么具体的外设是如何发送DMA请求的呢?

这里就要先提一下通道这个概念,不同的外设通过具体的通道向DMA控制器发送请求,然后DMA控制器再根据通道的优先权来处理请求。

DMA有DMA1和DMA2两个控制器,DMA1有7个通道,DMA2有5个通道,不同的DMA控制器的通道对应这不同的外设请求。

请添加图片描述

从上图可以看出,芯片的参考手册已经帮我们把不同的外设分别对应的通道分配好了,我们使用的时候只需要去查询这个表就行了。

仲裁器

虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能接收多个。

当多个通道同时向DMA控制器发送DMA请求的时候,谁可以先使用DMA控制器呢?这时就需要仲裁器来判断通道的优先级了。

仲裁器管理DMA通道请求分为两个阶段。

第一阶段属于软件阶段,可以在DMA_CCRx寄存器中设置,有4个等级:非常高四个优先级。见下图

请添加图片描述

第二阶段属于硬件阶段, 如果两个或以上的DMA通道请求设置的优先级一样,则他们优先级取决于通道编号,编号越低优先权越高,比如通道0高于通道1。

DMA数据配置

使用DMA,最核心的就是配置要传输的数据,包括数据从哪里来要到那里去传输数据的单位是什么要传多少数据是一次传输还是循环传输等等

从哪里来到那里去?

我们知道DMA传输数据的方向有三个:从外设到存储器,从存储器到外设,从存储器到存储器。 具体的传输方向DMA_CCR位4 DIR配置:0表示从外设到存储器,1表示从存储器到外设。 这里面涉及到的外设地址由DMA_CPAR配置,存储器地址由DMA_CMAR配置。

我们在使用固件库编程的时候,通常不会直接配置这三个寄存器,都是通过初始化结构体来配置的,这三个寄存器对应的结构体变量如下图:

请添加图片描述

配置内容对应寄存器
外设地址DMA_CPAR
存储器地址DMA_CMAR
传输方向DMA_CCR:DIR
外设到存储器

当我们使用从外设到存储器传输时,以ADC采集为例。DMA外设寄存器的地址对应的就是ADC数据寄存器的地址, DMA存储器的地址就是我们自定义的变量(用来接收存储AD采集的数据)的地址。方向我们设置外设为源地址。

存储器到外设

当我们使用从存储器到外设传输时,以串口向电脑端发送数据为例。DMA外设寄存器的地址对应的就是串口数据寄存器的地址, DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储通过串口发送到电脑的数据)的地址。方向我们设置外设为目标地址。

存储器到存储器

当我们使用从存储器到存储器传输时,以内部FLASH向内部SRAM复制数据为例。 DMA外设寄存器的地址对应的就是内部FLASH(我们这里把内部FALSH当作一个外设来看)的地址, DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储来自内部FLASH的数据)的地址。 方向我们设置外设(即内部FLASH)为源地址。跟上面两个不一样的是,这里需要把DMA_CCR位14:MEM2MEM:存储器到存储器模式配置为1,启动M2M模式。

数据要传多少,传的单位是什么?

请添加图片描述

配置内容对应寄存器
传输数目DMA_CNDTR
外设地址是否递增DMA_CCRx:PINC
存储器地址是否递增DMA_CCRx:MINC
外设数据宽度DMA_CCRx:PSIZE
存储器数据宽度DMA_CCRx:MSIZE

当我们配置好数据要从哪里来到哪里去之后,我们还需要知道我们要传输的数据是多少,数据的单位是什么。

以串口向电脑发送数据为例,我们可以一次性给电脑发送很多数据,具体多少由DMA_CNDTR配置, 这是一个32位的寄存器,一次最多只能传输65535个数据。

要想数据传输正确,源和目标地址存储的数据宽度还必须一致

串口数据寄存器是8位的, 所以我们定义的要发送的数据也必须是8位。

外设的数据宽度由**DMA_CCR的PSIZE[1:0]**配置, 可以是8/16/32位,

存储器的数据宽度由**DMA_CCR的MSIZE[1:0]**配置,可以是8/16/32位。

那么当PSIZE和MSIZE不相同时,也能传输,但是可能传输结果与你的预期不同,我们可以参照下表来查询:

请添加图片描述

在DMA控制器的控制下,数据要想有条不紊的从一个地方搬到另外一个地方,还必须正确设置两边数据指针的增量模式。

外设的地址指针由DMA_CCRx的PINC配置,存储器的地址指针由MINC配置。以串口向电脑发送数据为例,要发送的数据很多, 每发送完一个,那么存储器的地址指针就应该加1,而串口数据寄存器只有一个, 那么外设的地址指针就固定不变。具体的数据指针的增量模式由实际情况决定。

什么时候传输完成?

请添加图片描述

配置内容对应寄存器
模式选择(一次传输、循环传输)DMA_CCRx:CIRC
传输过半、传输完成、传输出错标志位DMA_ISR

数据什么时候传输完成,我们可以通过查询标志位或者通过中断的方式来鉴别。

每个DMA通道在DMA传输过半传输完成传输错误时都会有相应的标志位,如果使能了该类型的中断后,则会产生中断。

有关各个标志位的详细描述请参考DMA中断状态寄存器DMA_ISR的详细描述。

传输完成还分两种模式,是一次传输还是循环传输

一次传输很好理解,即是传输一次之后就停止,

要想再传输的话, 必须关断DMA使能后再重新配置后才能继续传输。

循环传输则是一次传输完成之后又恢复第一次传输时的配置循环传输, 不断的重复。

具体的由DMA_CCR寄存器的CIRC 循环模式位控制。

以上就是所有关于DMA的理论部分,下面我来进行程序编写。我先设计一个程序将存储器中的数据通过DMA的方式发送给串口。

我依然按照我上面讲DMA数据配置的顺序来写程序。

DMA(存储器到外设)实现代码

首先创建一个数组作为数据源,一会儿发送给串口

//准备将存储器中的这个数组中的数据发送到串口
u32 SourceBuffer[500];

然后开始配置DMA,上面我们讲DMA数据配置的时候已经说过了,我们配置DMA的时候是通过向DMA初始化结构体中填数据来配置的,所以我们先定义一个DMA初始化结构体,然后打开DMA外设的时钟信号。

//定义DMA初始化结构体
DMA_InitTypeDef DMA_initStruct;//首先查询DMA挂载在哪根总线上,然后打开DMA时钟信号
RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1EN,ENABLE);

数据从哪里来,到哪里去?

配置外设基地址

存储器基地址

数据传输方向

//通过上一篇文章对串口(USART)介绍的文章,可以找到串口数据发送的寄存器是放在USART_DR中的
DMA_initStruct.DMA_PeripheralBaseAddr = USART1_BASE + 0x04;//配置存储器的基地址,也就是数组名
DMA_initStruct.DMA_MemoryBaseAddr = (u32)SourceBuffer;//配置DMA数据传输方向,从存储器到外设,所以是外设Destination
DMA_initStruct.DMA_DIR = DMA_DIR_PeripheralDST;

数据要传多少,传的单位是什么?

我就不赘述了,请看代码中的注释

//配置发送的数据大小为500,因为数组大小为500
DMA_initStruct.DMA_BufferSize = 500;//外设地址不用自增,因为串口的发送寄存器只有一个字节这么大
DMA_initStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//配置外设的数据宽度为字节
DMA_initStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//由于数组是按顺序发送,所以存储器的地址可以自增
DMA_initStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;//由于数组中的数据类型为u32,所以存储器的数据宽度配置为字
DMA_initStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

什么时候传输完成?

//发送模式配置为发送一次,建议不要配置成循环发送,因为我的查看串口发送信息的工具会卡死
DMA_initStruct.DMA_Mode = DMA_Mode_Normal;//优先级随便配置,没人跟你抢
DMA_initStruct.DMA_Priority = DMA_Priority_High;//存储器到存储器的单独配置位,这里我们是存储器到外设,所以这个位为disable
DMA_initStruct.DMA_M2M = DMA_M2M_Disable;

上面配置好后,才算完成DMA初始化结构体的配置,接下来调用初始化函数。并给通道使能信号

//调用初始化函数
DMA_Init(DMA1_Channel4,&DMA_initStruct);//DMA通道使能信号
DMA_Cmd(DMA1_Channel4,ENABLE);

DMA配置好了,下面来写main函数,注意,串口也是需要配置的。但是由于我在上一篇文章里已经详细讲述过串口的配置方法,在这里我就直接调用串口的配置函数了。

int main(){u16 i;//先用一个for循环向数组中填数据,一会儿这个数据会通过串口发送出去for(i=0; i<500; i++){SourceBuffer[i]=14;}//调用串口配置函数USART_GPIO_Config();USART_Config();//调用DMA配置函数DMA_Config();//串口1向DMA发出TX请求USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);}

相关文章:

STM32—DMA直接存储器访问详解

DMA——直接存储器访问 DMA&#xff1a;Data Memory Access, 直接存储器访问。 DMA和我们之前学过的串口、GPIO都是类似的&#xff0c;都是STM32中的一个外设。串口是用来发送通信数据的&#xff0c;而DMA则是用来把数据从一个地方搬到另一个地方&#xff0c;而且不占用CPU。…...

【JavaEE初阶系列】——网络编程 TCP客户端/服务器 程序实现

目录 &#x1f6a9;TCP流套接字编程 &#x1f36d;ServerSocket API &#x1f36d;Socket API &#x1f36d;TCP服务器 &#x1f36d;TCP客户端 &#x1f6a9;TCP流套接字编程 俩个关键的类 ServerSocket (给服务器使用的类&#xff0c;使用这个类来绑定端口号&#xff0…...

CMake构建OpenCv并导入QT项目过程中出现的问题汇总

前言 再此之前请确保你的环境变量是否配置&#xff0c;这是总共需要配置的环境变量 E:\cmake\bin E:\OpenCv\opencv\build\x64\vc15\bin F:\Qt\Tools\mingw730_64\bin F:\Qt\5.12.4\mingw73_64\bin 问题一&#xff1a; CMake Error: CMake was unable to find a build program…...

AcWing 796. 子矩阵的和——算法基础课题解

AcWing 796. 子矩阵的和 题目描述 输入一个 n 行 m 列的整数矩阵&#xff0c;再输入 q 个询问&#xff0c;每个询问包含四个整数 x1,y1,x2,y2&#xff0c;表示一个子矩阵的左上角坐标和右下角坐标。 对于每个询问输出子矩阵中所有数的和。 输入格式 第一行包含三个整数 n&…...

macos 查看 远程服务器是否开放某个端口

想要使用mac查看远程服务器某个端口是否开发&#xff0c;可通过 nc 命令&#xff0c;如下&#xff1a; nc -zv <服务器IP> <端口号>如果该端口开发&#xff0c;结果为&#xff1a;succeeded! Connection to <服务器IP> port <端口号> [类型] succeed…...

GraphQL注入

GraphQL概述 GraphQL是一种查询语言&#xff0c;用于API设计和数据交互&#xff0c;不仅仅用于查询数据库。GraphQL 允许客户端在一个请求中明确地指定需要的数据&#xff0c;并返回预期的结果&#xff1b;并且将数据查询和数据修改分离开&#xff0c;大大增加灵活性。GraphQL…...

以太坊源码阅读01

正所谓区块链&#xff0c;怎能不熟悉区块的数据结构呢&#xff1f;区块的结构体被保存在core/types/block.go文件中&#xff0c;下面是我截取出来的&#xff1a; type Block struct {header *Headeruncles []*Headertransactions Transactionswithdrawals Withdr…...

Spark-Scala语言实战(15)

在之前的文章中&#xff0c;我们学习了如何在spark中使用键值对中的学习键值对方法中的lookup&#xff0c;cogroup两种方法。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#…...

【SpringBoot XSS存储漏洞 拦截器】Java纯后端对于前台输入值的拦截校验实现 一个类加一个注解结束

先看效果&#xff1a; 1.js注入拦截&#xff1a; 2.sql注入拦截 生效只需要两步&#xff1a; 1.创建Filter类&#xff0c;粘贴如下代码&#xff1a; package cn.你的包命.filter; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IO…...

【微信小程序】canvas开发笔记

【微信小程序】canvasToTempFilePath:fail fail canvas is empty 看说明书 最好是先看一下官方文档点此前往 如果是canvas 2d 写canvas: this.canvas,&#xff0c;如果是旧版写canvasId: ***, 解决问题 修改对应的代码&#xff0c;如下所示&#xff0c;然后再试试运行&#x…...

TripoSR: Fast 3D Object Reconstruction from a Single Image 论文阅读

1 Abstract TripoSR的核心是一个基于变换器的架构&#xff0c;专为单图像3D重建设计。它接受单张RGB图像作为输入&#xff0c;并输出图像中物体的3D表示。TripoSR的核心包括&#xff1a;图像编码器、图像到三平面解码器和基于三平面的神经辐射场&#xff08;NeRF&#xff09;。…...

u盘为什么一插上电脑就蓝屏,u盘一插电脑就蓝屏

u盘之前还好好的&#xff0c;可以传输文件&#xff0c;使用正常&#xff0c;但是最近使用时却出现问题了。只要将u盘一插入电脑&#xff0c;电脑就显示蓝屏。u盘为什么一插上电脑就蓝屏呢?一般&#xff0c;导致的原因有以下几种。一&#xff0c;主板的SATA或IDE控制器驱动损坏…...

【Redis】redis面试相关积累

Redis到底是多线程还是单线程&#xff1f; Redis 在设计上是单线程的&#xff0c;这意味着 Redis 服务器在任何给定时刻只能执行一个命令。然而&#xff0c;这并不意味着 Redis 无法利用多核 CPU&#xff0c;因为 Redis 使用了一些技术来提高性能和并发性&#xff0c;例如非阻…...

【Linux】进程的状态(运行、阻塞、挂起)详解,揭开孤儿进程和僵尸进程的面纱,一篇文章万字讲透!!!!进程的学习②

目录 1.进程排队 时间片 时间片的分配 结构体内存对齐 偏移量补充 对齐规则 为什么会有对齐 2.操作系统学科层面对进程状态的理解 2.1进程的状态理解 ①我们说所谓的状态就是一个整型变量&#xff0c;是task_struct中的一个整型变量 ②.状态决定了接下来的动作 2.2运行状态 2.…...

前端js基础知识(八股文大全)

一、js的数据类型 值类型(基本类型)&#xff1a;数字(Number)、字符串&#xff08;String&#xff09;、布尔(Boolean)、对空&#xff08;Null&#xff09;、未定义&#xff08;Undefined&#xff09;、Symbol,大数值类型(BigInt) 引用数据类型&#xff1a;对象(Object)、数组…...

316_C++_xml文件解析成map,可以放到表格上 + xml、xlsx文件互相解析

xml文件例如&#xff1a; <?xml version"1.0" encoding"UTF-8" standalone"yes"?> <TrTable> <tr id"0" label"TR_PB_CH" text"CH%2"/> <tr id"4" label"TR_PB_CHN"…...

未来汽车硬件安全的需求(2)

目录 4.汽车安全控制器 4.1 TPM2.0 4.2 安全控制器的硬件保护措施 5. EVITA HSM和安全控制器结合 6.小结 4.汽车安全控制器 汽车安全控制器是用于汽车工业安全关键应用的微控制器。 他们的保护水平远远高于EVITA HSM。今天的典型应用是移动通信&#xff0c;V2X、SOTA、…...

html+javascript,用date完成,距离某一天还有多少天

图片展示: html代码 如下: <style>* {margin: 0;padding: 0;}.time-item {width: 500px;height: 45px;margin: 0 auto;}.time-item strong {background: orange;color: #fff;line-height: 100px;font-size: 40px;font-family: Arial;padding: 0 10px;margin-right: 10px…...

跟bug较劲的第n天,undefined === undefined

前情提要 场景复现 看到这张图片&#xff0c;有的同学也许不知道这个冷知识&#xff0c;分享一下&#xff0c;是因为我在开发过程中踩到的坑&#xff0c;花了三小时排查出问题的原因在这&#xff0c;你们说值不值。。。 我分享下我是怎么碰到的这个问题&#xff0c;下面看代码…...

数据结构_基于链表的通讯录

顺序表的源代码需要略作修改&#xff0c;如下 将数据类型改为通讯录的结构体。注释掉打印&#xff0c;查找的函数。 SList.h #define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> #include<stdlib.h> #include<assert.h> #include"Contact.h"ty…...

jenkins+gitlab配置

汉化 1、安装Localization: Chinese (Simplified)插件 &#xff08;此处我已安装&#xff09; &#xff08;安装完成后重启jenkins服务即可实现汉化&#xff09; 新增用户权限配置 1、安装插件 Role-based Authorization Strategy 2、全局安全配置 3、配置角色权限 4、新建…...

【Labview】虚拟仪器技术

一、背景知识 1.1 虚拟仪器的定义、组成和应用 虚拟仪器的特点 虚拟仪器的突出特征为“硬件功能软件化”&#xff0c;虚拟仪器是在计算机上显示仪器面板&#xff0c;将硬件电路完成信号调理和处理功能由计算机程序完成。 虚拟仪器的组成 硬件软件 硬件是基础&#xff0c;负责将…...

IvorySQL 3.2原理解析|与Oracle 12c XML函数兼容性的实现机制

[发行日期&#xff1a;2024年4月11日] IvorySQL 3.2基于PostgreSQL 16.2&#xff0c;引入了多种Oracle XML函数的全面兼容性功能&#xff0c;同时修复了多个问题&#xff0c;更多信息请参考文档网站。 >>>新版本体验链接&#xff1a; https://docs.ivorysql.org/cn…...

SpringBoot + Dobbo + nacos

SpringBoot Dobbo nacos 一、nacos https://nacos.io/zh-cn/docs/quick-start.html 1、下载安装包 https://github.com/alibaba/nacos/releases/下载后在主目录下&#xff0c;创建一个logs的文件夹&#xff1a;用来存日志 2、启动nacos 在bin目录下打开cmd运行启动命令&a…...

学习笔记-微服务基础(黑马程序员)

框架 spring cloudspring cloud alibaba Eureka eureka-server 注册中心 eureka-client 客户端每30s发送心跳服务 服务消费者服务提供者 server 依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-star…...

每日Bug汇总--Day05

Bug汇总—Day05 一、项目运行报错 二、项目运行Bug 1、**问题描述&#xff1a;**前端将从后台查询的数据作为参数进行get请求&#xff0c;参数为空 原因分析&#xff1a; 这种写法可能只支全局的参数调用方法的传参响应 代码实现 if (this.jishiName) {this.$http({url…...

docker、ctr、crictl命令对比

命令dockerctr&#xff08;containerd&#xff09;crictl&#xff08;kubernetes&#xff09;查看运行的容器docker psctr task ls/ctr container lscrictl ps查看镜像docker imagesctr image lscrictl images查看容器日志docker logs无crictl logs查看容器数据信息docker insp…...

uniapp 编译后分包下静态图片404问题解决方案

如上图官方说明&#xff1a; 在分包下建立一个static文件夹即可&#xff1a; 分包内代码引用图片 <image src"/分包名称/img/图片名称"></image> <image src"/dataView/img/图片名称"></image>...

第十二届蓝桥杯大赛软件赛省赛Java 大学 B 组题解

1、ASC public class Main {public static void main(String[] args) {System.out.println(...

关于openai和chatgpt、gpt-4、PyTorch、TensorFlow 两者和Transformers的关系

近两年&#xff0c;随着人工智能的火爆&#xff0c;不论通过哪个渠道&#xff0c;相信我们都听说过openai、gpt等这类名词&#xff0c;那么它们到底是什么意思&#xff0c;请看下文。 openai:是一家人工智能公司&#xff1b; openai-api&#xff1a;是openai提供的api&#xf…...

流量网站应该怎么做/百度seo排名点击器

一、什么是AS&#xff08;ActionScript&#xff09; ActionScript&#xff0c;简称AS&#xff0c;中译为“动作脚本语言”。 用于在Flash上实现一些光用Flash无法实现的功能。 在Flash界面下的动作面板中编写AS。 二、时间轴控制命令 初识AS&#xff0c;首先让我们来认识一下AS…...

wordpress 营销页面/怎样做竞价推广

福建师范大学网络与继续教育学院《计算机应用基础》期末考试A 卷姓名&#xff1a;专业&#xff1a;学号&#xff1a;学习中心&#xff1a;成绩&#xff1a;一、单项选择题(答案务必写在表格中&#xff0c;每小题1 分&#xff0c;共 30 分)12345678910CCCCBBCCAC111213141516171…...

黄页大全18勿看2000网站/员工培训内容

天边最初的一抹光亮黎明时分的到来&#xff0c;是由天边最初的一抹光亮标识的。但这光亮仅仅是在天际线附近&#xff0c; 甚至满天的星斗还在与它争辉。在这一时段拍摄&#xff0c;除了天边一道亮光外&#xff0c;其他的地方的光线还是非常暗的。此时拍摄&#xff0c;一定需要长…...

如何查询网站空间商/手游推广代理平台有哪些

今天介绍一下lamp环境的配置。 服务器用的是阿里云的服务器。 L&#xff1a;centos、A&#xff1a;apache、M&#xff1a;mysql、P&#xff1a;php &#xff08;一&#xff09;安装apache 我们这里安装的是httpd &#xff08;1&#xff09;安装httpd # yum install httpd…...

企业网站推广的收获与启示/软件培训

as3 flash和android java类似&#xff0c;都是加一个一个的监听器&#xff0c;然后在回调函数里面处理事务win32的开发&#xff0c;是直接去扫描句柄信号做判断&#xff0c;as3 还有android java&#xff0c;相当于对句柄写好了可以录入函数的接口&#xff0c;等待你录入回调函…...

网站建设jsp/seo是什么专业

今天和大家分享10个批量快速处理PPT 的技巧&#xff01;没错&#xff01;就是你想的“批发”处理~话不多说&#xff0c;赶紧一起来学习吧~一、批量提取PPT模板里的元素 在制作PPT的过程中&#xff0c;经常会遇到自己喜欢的模板&#xff01;可真正喜欢的是里面的素材&#xff0c…...