STM32之DMA

一、DMA概述

DMA:直接寄存器访问

Direction:直接        Memory:存储器        Access:访问

就是一个外设用于搬运数据,就是一个搬运工。

在串口发送数据的时候:这种效率并不高

如何想要发送大量的数据的时候可以利用DMA

1、DMA工作流程

没有DMA参与的uart的收发过程

2、有DMA参与的uart的收发过程

DMA就可以一直搬运数据,核心首先要控制以下DMA开始搬运

优点:可以解放CPU,让他可以去做别的事情

2、STM32的DMA控制器概述

直接存储器访问 (DMA) 用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。DMA 控制器基于复杂的总线矩阵架构,将功能强大的双 AHB 主总线架构与独立的 FIFO 结合在一起,优化了系统带宽。两个 DMA 控制器总共有 16 个数据流每个控制器 8 ),每一个 DMA 控制器都用于管理一个或多个外设的存储器访问请求。每个数据流总共可以有多达 8 个通道(或称请求)。每个通道都有一个仲裁器,用于处理 DMA请求间的优先级。

DMA的搬运方向:外设与存储器之间以及存储器与存储器

一共有两个DMA控制器,每个DMA控制器都有8个数据流,每个数据流有8个通道

128个通道(请求)

不能同时响应就会有先帮谁搬的问题,这个问题由仲裁器解决(它的优先级级别比较少)

如果仲裁器解决不了,就由数据流的编号解决(数字越小优先级越高)

3、STM32的DMA控制器特征

DMA 主要特性是:
双 AHB 主总线架构,一个用于存储器访问,另一个用于外设访问
仅支持 32 位访问的 AHB 从编程接口
每个 DMA 控制器有 8 个数据流,每个数据流有多达 8 个通道(或称请求
每个数据流有单独的四级 32 位先进先出存储器缓冲区 (FIFO),可用于 FIFO 模式或直接模式:
— FIFO 模式:可通过软件将阈值级别选取为 FIFO 大小的 1/4、 1/2 或 3/4
— 直接模式
    每个 DMA 请求会立即启动对存储器的传输。当在直接模式(禁止 FIFO)下将 DMA请求配置为以存储器到外设模式传输数据时, DMA 仅会将一个数据从存储器预加载到内部 FIFO,从而确保一旦外设触发 DMA 请求时则立即传输数据。

通过硬件可以将每个数据流配置为:
支持外设到存储器存储器到外设存储器到存储器(只能是DMA2上面的数据流来控制传输的常规通道(DMA搬运数据的三大方向)

 也支持在存储器方双缓冲的双缓冲区通道
8 个数据流中的每一个都连接到专用硬件 DMA 通道(请求)(厂家在出厂时已经规定好当前那个外设可以和DMA相连来搬运数据)
DMA 数据流请求之间的优先级可用软件编程(4 个级别:非常高、高、中、低),在软件优先级相同的情况下可以通过硬件决定优先级(例如,请求 0 的优先级高于请求 1 )
每个数据流也支持通过软件触发存储器到存储器的传输(仅限 DMA2 控制器
可供每个数据流选择的通道请求多达 8 个。此选择可由软件配置,允许几个外设启动 DMA
请求
要传输的数据项的数目(要搬多少次)可以由 DMA 控制器或外设管理:
DMA 流控制器:要传输的数据项的数目是 1 到 65535,可用软件编程
外设流控制器:要传输的数据项的数目未知并由源或目标外设控制,这些外设通过
硬件发出传输结束的信号(SDIO)
独立的源和目标传输宽度(字节、半字、字):源和目标的数据宽度不相等时, DMA 自动
封装 /解封必要的传输数据来优化带宽。这个特性仅在 FIFO 模式下可用

1个字节 = 8个位

半字 = 2个字节 = 16个位

字 = 4个字节 = 32个位


对源和目标的增量或非增量寻址(一般就是存储器的地址需要递增,外设的地址不需要递增)
支持 4 个、 8 个和 16 个节拍的增量突发传输。突发增量的大小可由软件配置,通常等于外设 FIFO 大小的一半
每个数据流都支持循环缓冲区管理
5 个事件标志( DMA 半传输、 DMA 传输完成、 DMA 传输错误、 DMA FIFO 错误、直接
模式错误),进行逻辑或运算,从而产生每个数据流的单个中断请求

4、STM32的DMA控制器框架

二、DMA功能

1、通道选择

通道的配置一个时刻只能有一个请求到某一个数据流,但是在某一个时刻可能会有多个数据流请求(数据流的优先级问题)每个数据流都与一个 DMA 请求相关联,此 DMA 请求可以从 8 个可能的通道请求中选出。
此选择由 DMA_SxCR 寄存器中的 CHSEL[2:0] 位控制。

DMA1:

DMA2:

2、仲裁器

仲裁器为两个 AHB 主端口(存储器和外设端口)提供基于请求优先级的 8 个 DMA 数据流请求管理,并启动外设 /存储器访问序列。
优先级管理分为两个阶段:
软件:每个数据流优先级都可以在 DMA_SxCR 寄存器中配置。分为四个级别:

非常高优先级

高优先级
中优先级
低优先级
硬件:如果两个请求具有相同的软件优先级,则编号低的数据流优先于编号高的数据流。例如,数据流 2 的优先级高于数据流 4。

3、FIFO模式与直接模式

FIFO模式

FIFO 用于在源数据传输到目标之前临时存储这些数据。每个数据流都有一个独立的 4 FIFO,阈值级别可由软件配置为 1/4 1/23/4 。为了使能 FIFO 阈值级别,必须通过将 DMA_SxFCR 寄存器中的 DMDIS 位置 1 来禁止直接模式。FIFO 的结构随源与目标数据宽度而不同,

FIFO缓冲区的大小为4字 = 16字节

默认情况下, FIFO 以直接模式操作(将 DMA_SxFCR 中的 DMDIS 位置 1 ),不使用 FIFO阈值级别。如果在每次 DMA 请求之后,系统需要至/自存储器的立即和单独传输,这种模式非常有用。当在直接模式(禁止 FIFO)下将 DMA 配置为以存储器到外设模式传输数据时DMA 会将一 个数据从存储器预加载到内部 FIFO,从而确保一旦外设触发 DMA 请求时则立即传输数据。为了避免 FIFO 饱和,建议使用高优先级配置相应的数据流。
该模式仅限以下方式的传输:
源和目标传输宽度相等,并均由 DMA_SxCR 中的 PSIZE[1:0] 位定义(MSIZE[1:0] 位的
状态是“无关”
不可能进行突发传输(DMA_SxCR 中的 PBURST[1:0] 和 MBURST[1:0] 位的状态是“
关”

4、突发增量(仅在FIFO模式下才能使用)

选择 FIFO 阈值(DMA_SxFCR 寄存器的位 FTH[1:0])和存储器突发大小(DMA_SxCR 寄存
器的 MBURST[1:0] 位)时需要小心: FIFO 阈值指向的内容必须与整数个存储器突发传输完全 匹配。如果不是这样,当使能数据流时将生成一个 FIFO 错误( DMA_HISR 或 DMA_LISR寄存器的标志 FEIFx),然后将自动禁止数据流。

5、源与目标、传输方向

(1)、外设到存储器模式

使能这种模式(将 DMA_SxCR 寄存器中的位 EN 置 1 ) 时,每次产生外设请求,数据流都会启动数据源到 FIFO 的传输。达到 FIFO 的阈值级别时, FIFO 的内容移出并存储到目标中。如果 DMA_SxNDTR 寄存器达到零、外设请求传输终止(在使用外设流控制器的情况下)或DMA_SxCR 寄存器中的 EN 位由软件清零,传输即会停止。

在直接模式下(当 DMA_SxFCR 寄存器中的 DMDIS 值为“0”时),不使用 FIFO 的阈值级别控制:每完成一次从外设到 FIFO 的数据传输后,相应的数据立即就会移出并存储到目标中。只有赢得了数据流的仲裁后,相应数据流才有权访问 AHB 源或目标端口。系统使用在DMA_SxCR 寄存器 PL[1:0]。

(2)、存储器到外设模式

使能这种模式(将 DMA_SxCR 寄存器中的 EN 位置 1 )时,数据流会立即启动传输,从源完全填充 FIFO。每次发生外设请求,FIFO 的内容都会移出并存储到目标中。当 FIFO 的级别小于或等于预定义的阈值级别时,将使用存储器中的数据完全重载 FIFO。

如果 DMA_SxNDTR 寄存器达到零、外设请求传输终止(在使用外设流控制器的情况下)或
DMA_SxCR 寄存器中的 EN 位由软件清零,传输即会停止。
在直接模式下(当 DMA_SxFCR 寄存器中的 DMDIS 值为“0”时),不使用 FIFO 的阈值级别。一旦使能了数据流, DMA 便会预装载第一个数据,将其传输到内部 FIFO。一旦外设请求数据传输, DMA 便会将预装载的值传输到配置的目标。然后,它会使用要传输的下一个数据再次重载内部空 FIFO。预装载的数据大小为 DMA_SxCR 寄存器中 PSIZE 位字段的值。只有赢得了数据流的仲裁后,相应数据流才有权访问 AHB 源或目标端口。系统使用在DMA_SxCR 寄存器。

(3)、存储器到存储器模式

        DMA 通道在没有外设请求触发的情况下同样可以工作。此为图 30 中介绍的存储器到存储器
模式。通过将 DMA_SxCR 寄存器中的使能位 (EN) 置 1 来使能数据流时,数据流会立即开始填充 FIFO,直至达到阈值级别。达到阈值级别后, FIFO 的内容便会移出,并存储到目标中。如果 DMA_SxNDTR 寄存器达到零或 DMA_SxCR 寄存器中的 EN 位由软件清零,传输即会停止。(不允许使用直接模式)
        只有赢得了数据流的仲裁后,相应数据流才有权访问 AHB 源或目标端口。系统使用在DMA_SxCR 寄存器 PL[1:0] 位中为每个数据流定义的优先级执行仲裁。注意: 使用存储器到存储器模式时,不允许循环模式和直接模式只有 DMA2 控制器能够执行存储器到存储器的传输。

6、地址递增

根据 DMA_SxCR 寄存器中 PINC 和 MINC 位的状态,外设和存储器指针在每次传输后可以自动向后递增或保持常量通过单个寄存器访问外设源或目标数据时,禁止递增模式十分有用。如果使能了递增模式,则根据在 DMA_SxCR 寄存器 PSIZEMSIZE 位中编程的数据宽度,下一次传输的地址将是前一次传输的地址递增 1 (对于字节)、 2(对于半字)或 4(对于字)。--设置的递增大小和psizeMSIZE有关
为了优化封装操作,可以不管 AHB 外设端口上传输的数据的大小,将外设地址的增量偏移大小固定下来(设置递增的大小是一个固定值)。 DMA_SxCR 寄存器中的 PINCOS 位用于将增量偏移大小与外设 AHB 端口或32 位地址(此时地址递增 4)上的数据大小对齐。 PINCOS 位仅对 AHB 外设端口有影响。如果将 PINCOS 位置 1 ,则不论 PSIZE 值是多少,下一次传输的地址总是前一次传输的地址递增 4(自动与 32 位地址对齐) 。但是, AHB 存储器端口不受此操作影响。如果 AHB 外设端口或 AHB 存储器端口分别请求突发事务,为了满足 AMBA 协议(在固定地址模式下不允许突发事务),则需要将 PINC 或 MINC 位置 1

三、DMA相关寄存器

DMA 数据流 x 配置寄存器 (DMA_SxCR) (x = 0..7)

25-27位用于通道选择,只有还没使能DMA的时候才可以配置

突发模式只能针对FIFO模式来用,只有还没使能DMA的时候才可以配置

位15有效的前提是PINC位置1,也就是PINC位如果等于0则外设地址不递增

每搬一次数据到fifo里是以什么为单位,在直接模式下,MSIZE写入的值一定是和PSIZE的大小一致。

置0时,就不递增,置1时每次递增的数据就是以 MSIZE的大小为准。

DMA 数据流 x 数据项数寄存器 (DMA_SxNDTR) (x = 0..7)

搬多少次写什么值,每搬一次数据和当前的MSIZE或者PSIZE有关。

DMA 数据流 x 外设地址寄存器 (DMA_SxPAR) (x = 0..7)

填入的时当前这个外设的基地址(填进来的是地址数据的形式)。

DMA 数据流 x 存储器 0 地址寄存器 (DMA_SxM0AR) (x = 0..7)

填入的时当前这个存储器的基地址(填进来的是地址数据的形式)。

DMA 数据流 x FIFO 控制寄存器 (DMA_SxFCR) (x = 0..7) 

位2写0代表使用直接模式,写1代表fifo模式。

0-1 位设置FIFO 的阈值级别,在直接模式下,这些位的写入没有意义。

四、例子

用USART1_TX端要连接到DMA2的数据流7的通道4上

软件实现

串口的DMA可以正常工作(响应请求)

打开DMA2的时钟

常用的配置(围绕CR寄存器)

从哪里搬到哪里? -- 方向(存储器到外设,设置当前的源地址和目标地址)

搬多少次? -- 由数据项数寄存器决定(NDTR)

每搬一次的大小?--MSIZE和PSZIE

使能数据流

存储器到外设

#include "dma.h"

/************************************
函数功能:DMA2的数据流7通道4的初始化
函数形参:
u8 *buf -- 存储器的地址
u16 len -- 数据的大小(要搬多少次)
函数返回值:void
函数说明:可以完成USART1通过DMA往外界搬运数据
存储器到外设
作者:
日期:
************************************/
void Dma2_Stream7_Init(u8 *buf,u16 len)
{
	//发送使能 DMA 模式。
	USART1->CR3 |= 0X1 << 7;
	
    //	1.打开DMA2的时钟
	RCC->AHB1ENR |= 0X1 << 22;
	
    //	2.常用的配置(围绕CR寄存器)
	
	//使用直接模式
	DMA2_Stream7->FCR &= ~(0x1 << 2);
	DMA2_Stream7->CR = 0;
	/*
		P和M都是单次传输,不使用突发传输
		当前目标存储器为存储器0
		不使用双缓冲
		低优先级
		外设地址指针固定
		MSIZE和PSZIE都是1个字节
		禁止循环模式
		DMA是流控制器
	*/
	
	//数据流7选择的是通道4
	DMA2_Stream7->CR |= (0x4 << 25);
	
	//存储器地址递增
	DMA2_Stream7->CR |= 0x1 << 10;

	//3.从哪里搬到哪里?
	//	存储器到外设
		DMA2_Stream7->CR |= 0x1 << 6;

	//设置当前的源地址和目标地址
	DMA2_Stream7->PAR = (u32)&(USART1->DR);//目标地址
	DMA2_Stream7->M0AR = (u32)buf;//源地址
	
	//4.搬多少次? -- 由数据项数寄存器决定(NDTR)
	DMA2_Stream7->NDTR = len;
	
	//5.使能数据流
	DMA2_Stream7->CR |= 0x1 << 0;
}

存储器到存储器

/************************************
函数功能:DMA2的数据流5通道2的初始化
函数形参:
u32 *par
u32 *m0ar 
u16 len -- 数据的大小(要搬多少次)
函数返回值:void
函数说明:存储器到存储器
作者:
日期:
************************************/
void Dma2_Stream5_Init(u8 *par,u8 *m0ar,u16 len)
{
	
    //	1.打开DMA2的时钟
	RCC->AHB1ENR |= 0X1 << 22;
	
    //	2.常用的配置(围绕CR寄存器)
	
	//使用fifo模式
	DMA2_Stream5->FCR |= (0x1 << 2);
	
	//阈值级别为4字节
	DMA2_Stream5->FCR &= ~(0x3 << 0);
	
	DMA2_Stream5->CR = 0;
	/*
		当前目标存储器为存储器0
		不使用双缓冲
		MSIZE和PSZIE都是1个字节
		禁止循环模式
		DMA是流控制器
	*/
	
	
	//数据流5选择的是通道2
	DMA2_Stream5->CR |= (0x2 << 25);
	
	//外设4节拍的突发
	DMA2_Stream5->CR |= 0x1 << 21;
	
	//软件优先级为高
	DMA2_Stream5->CR |= 0x2 << 16;
	
	//外设地址递增(psize)
	DMA2_Stream5->CR |= 0x1 << 9;
	
	//存储器地址递增
	DMA2_Stream5->CR |= 0x1 << 10;
	

	//3.从哪里搬到哪里?
	//	存储器到存储器
		DMA2_Stream5->CR |= 0x2 << 6;

	//设置当前的源地址和目标地址
	DMA2_Stream5->PAR = (u32)par;//目标地址
	DMA2_Stream5->M0AR = (u32)m0ar;//源地址
	
	
	//4.搬多少次? -- 由数据项数寄存器决定(NDTR)
	DMA2_Stream5->NDTR = len;
	
	//5.使能数据流
	DMA2_Stream5->CR |= 0x1 << 0;
}

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

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

相关文章

【友提】2023年“思维100”编程比赛开始报名,名额有限报名抓紧

根据官方昨天发布的通知&#xff0c;2023年上海市“科学小公民”实践展示活动之“思维100”STEM应用能力编程活动&#xff08;秋季&#xff09;开始报名了&#xff0c;为便于大家了解&#xff0c;六分成长为大家整理关键信息如下。为便于叙述&#xff0c;该活动简称为思维100编…

RGB颜色空间与BMP格式图片

RGB颜色空间 RGB可以分为两大类&#xff1a;一种是索引形式&#xff0c;一种是像素形式&#xff1a; 索引形式&#xff1a;存储每个像素在调色板中的索引 RGB1&#xff1a;每个像素用1bit表示&#xff0c;调色板中只包含两种颜色&#xff08;黑白&#xff09;RGB4&#xff1a…

卸载本地开发环境,拥抱容器化开发

以前在公司的时候&#xff0c;使用同事准备的容器化环境&#xff0c;直接在 Docker 内进行开发&#xff0c;爽歪歪呀。也是在那时了解了容器化开发的知识&#xff0c;可惜了&#xff0c;现在用不到那种环境了。所以打算自己在本地也整一个个人的开发环境&#xff0c;不过因为我…

吴恩达《机器学习》8-3->8-4:模型表示I、模型表示II

8.3、模型表示I 一、大脑神经网络的基本原理 为了构建神经网络模型&#xff0c;首先需要理解大脑中的神经网络是如何运作的。每个神经元都可以被看作是一个处理单元或神经核&#xff0c;它包含多个输入&#xff08;树突&#xff09;和一个输出&#xff08;轴突&#xff09;。…

在vue3中使用Element-plus的图标

首先安装Element-Plus-icon # 选择一个你喜欢的包管理器# NPM $ npm install element-plus/icons-vue # Yarn $ yarn add element-plus/icons-vue # pnpm $ pnpm install element-plus/icons-vue 如何使用 Element-Plus-icon官方文档链接Icon 图标 | Element Plus (element-…

【操作系统】1.1 操作系统的基础概念、功能以及特性

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

Unity之NetCode多人网络游戏联机对战教程(8)--玩家位置同步

文章目录 前言添加相机玩家添加对应组件服务端权威&#xff08;server authoritative&#xff09;客户端权威&#xff08;client authoritative&#xff09;服务端同步位置阅读与理解PlayerTransformSync.csNetworkVariableUploadTransformSyncTransform 后话 前言 承接上篇&a…

LOW-POWER AUDIO KEYWORD SPOTTING USING TSETLIN MACHINES

基于TM的低功耗语音关键字识别 摘要1介绍2TM的介绍3KWS的音频预处理技术4实验结果MFC4.1C设置分位数数量4.3增加关键词数量4.4 声音相似的关键词4.5 每个类别的子句数量对KWS-TM的比较学习收敛和复杂性分析 摘要 在本文中&#xff0c;我们探讨了一种基于TM的关键词识别&#x…

《算法通关村——透彻理解二叉树中序遍历的应用》

《算法通关村——透彻理解二叉树中序遍历的应用》 直接上题 108. 将有序数组转换为二叉搜索树 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高…

同一个Unity项目打开两个Unity Editor实例

特殊情况下&#xff0c;同一个项目需要同时打开两个编辑器做测试&#xff0c;如多人在线游戏&#xff0c;或者有通信功能的时候就有这样的需求。同时也为了方便调试和观察日志。并且修改的是同一份代码。 命令介绍&#xff1a; 实现思路&#xff1a; 使用 mklink 命令 分别创建…

深入研究SVN代码检查的关键工具:svnchecker vs. SonarQube,选择最适合你的代码检查工具

目录 一、SVN代码检查(整合svnchecker)1、创建SVN代码库2、下载安装包3、修改SVN配置4、新建代码检查配置文件(名称自定义)5、hooks目录添加配置文件6、设置只对Java文件进行检查7、测试 二、SonarQube代码检测1、什么是SonarQube2、MySQL数据库的安装3、SonarQube服务端软件安…

530. 二叉搜索树的最小绝对差

题目描述 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的绝对值。 示例 1&#xff1a; 输入&#xff1a;root [4,2,6,1,3] 输出&#xff1a;1示例 2&#xff1a; ) 输入&#…

边缘分布式机器学习

目录 通信机制同步Synchronous异步Asynchronous半同步/延时同步通信的拓扑结构基于迭代式MapReduce的通信&#xff08;同步模式&#xff09;基于MPI之AllReduce的通信&#xff08;同步模式&#xff09;AllReduce有很多变种 基于参数服务器的通信&#xff08;多为异步&#xff0…

[mysql]索引优化-2

目录 一、分页查询优化1.根据自增且连续的主键排序的分页查询2.根据非主键字段排序的分页查询 二、Join关联查询优化1.嵌套循环连接 Nested-Loop Join(NLJ) 算法2.基于块的嵌套循环连接 Block Nested-Loop Join(BNL)算法 三、count(*)查询优化1.查询mysql自己维护的总行数2.sho…

Linux进程空间地址

程序地址空间回顾 问题引入 ---------------明天再写0.0

Zyxel NBG2105 身份验证绕过

直接访问如下payload则会以管理员身份跳转到 home.htm页面 ​​/login_ok.htm漏洞证明 查看本页面的cookie&#xff0c;login为1 文笔生疏&#xff0c;措辞浅薄&#xff0c;望各位大佬不吝赐教&#xff0c;万分感谢。 免责声明&#xff1a;由于传播或利用此文所提供的信息、…

Linux文件缓冲区

文章目录 1. 缓冲区现象2. 用户级和系统级缓冲区3. 缓冲区刷新4. 为什么要有缓冲区5. 文件打印的全缓冲6. 模拟实现C语言文件标准库 本章gitee代码仓库&#xff1a;重定向、模拟C语言文件标准库 1. 缓冲区现象 我们这里分别调用了4个差不多的函数&#xff0c;但是结果是有一定差…

【云备份项目两万字总结】服务端篇 -----附源码

项目总结 整体回顾逐步实现utill.hppconfig.hppdata.hpphot.hppservice.hpp 代码 整体回顾 服务端的目标是&#xff1a; 对客户端的请求进行处理管理客户端上传的文件 于客户端进行数据交换&#xff0c;我们需要引入网络&#xff0c;所以我们引入第三方库----httplib.h库&am…

如何在 Python 中执行 MySQL 结果限制和分页查询

Python MySQL 限制结果 限制结果数量 示例 1: 获取您自己的 Python 服务器 选择 “customers” 表中的前 5 条记录&#xff1a; import mysql.connectormydb mysql.connector.connect(host"localhost",user"您的用户名",password"您的密码"…