【STM32】DMA

news2024/11/14 13:55:44

描述

大部分图片来源:正点原子HAL库课程

 专栏目录:记录自己的嵌入式学习之路-CSDN博客


目录

0    概述

1    原理(用于个人理解的,非常重要!)

1.1    DMA请求

1.2    循环模式与DMA请求的关系

1.3    传输完成中断(TC)发生的时机

2    硬件情况

3    作用

4    DMA的优先级

4.1    软件优先级

4.2    硬件优先级

4.3    优先级的作用

5    数据流方向

5.1    外设到存储器

5.2    存储器到外设

5.3    存储器到存储器

5.4    配置

6    外设/存储器地址增量模式

7    传输的数据宽度

8    传输结束时机(循环与否)

8.1    中断的不同

8.2    对循环模式的支持

9    其他特性

9.1    最大传输数

9.2    内存到内存的传输

10    相关HAL库函数

11    重要结构体

12    配置步骤

13    注意事项


0    概述

DMA,全称为:Direct Memory Access,即直接存储器访问。

DMA牛逼的地方应该就是将一个外设的数据内容直接映射到内存中的一堆数据中,通过读数据就读到了外设通过GPIO输入的某些值,就不需要使用CPU费劲巴拉地去访问寄存器获取这些值。


1    原理(用于个人理解的,非常重要!)

1.1    DMA请求

如果外设想要通过DMA来传输数据,必须先给DMA控制器发送DMA请求,DMA收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且DMA控制器收到应答信号之后,就会启动DMA的传输,直到传输完毕。

1.2    循环模式与DMA请求的关系

我的理解是:

在非循环模式下,外设发出了DMA请求,若此时CNDTR寄存器的值不为0,则DMA根据设定的数据宽度执行一次数据搬运;而如果CNDTR寄存器的值已经为0了,DMA将不会响应外设的数据搬运请求。

而在循环模式下,CNDTR寄存器清零后会重新置为用户设定的值,并继续响应外设的DMA请求。

1.3    传输完成中断(TC)发生的时机

CNDTR寄存器的值减到0的时候。并不是一个数据宽度搬运完毕的时候。


2    硬件情况

STM32F1有两个DMA控制器:DMA1和DMA2。其分别拥有7个和5个通道。各通道对应不同的外设,见下图:


  • 可在《STM32F10xxx参考手册》查询。

3    作用

DMA传输将数据从一个地址空间复制到另一个地址空间。

其无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。减轻了CPU的负担。


4    DMA的优先级

4.1    软件优先级

程序可设置DMA通道的软件优先级,有最高、高、中、低四个优先级。

4.2    硬件优先级

在软件优先级相同的情况下,硬件的通道编号越小,优先级越高。且DMA1优先级比DMA2高。

4.3    优先级的作用

多个请求通过逻辑或输入到DMA控制器,只能有一个请求有效。所以需要优先级处理这个情况。


5    数据流方向

5.1    外设到存储器

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

5.2    存储器到外设

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

5.3    存储器到存储器

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

5.4    配置

寄存器中通过MEM2MEM、DIR两个寄存器对数据的流向进行配置:



6    外设/存储器地址增量模式

就是传输过程中有一个指针指向外设/存储器,在写完一个后自动往后移动指针。对于串口传输的情况,由于存储器是需要传输完一个自动往下再传输,因此应该使能存储器地址增量模式。而对于外设串口,因为只是往其DR寄存器中传输数据,并没有指针移动的操作,因此就不需要使能外设地址增量模式。

野火HAL库教程的解释:以串口向电脑发送数据为例,要发送的数据很多,每发送完一个,那么存储器的地址指针就应该加1,而串口数据寄存器只有一个,那么外设的地址指针就固定不变。


7    传输的数据宽度

在寄存器可以设置存储器和外设的数据宽度,一般来说,两者应该设置为一致的,一般以外设的为准。例如串口的数据寄存器是8位的,因此外设和存储器的数据宽度都要设置为8位。

当实在是需要源数据和目标数据宽度不一致的情况时,需要查阅《STM32F10xxx参考手册》,如下图的表格。


8    传输结束时机(循环与否)

数据什么时候传输完成,我们可以通过查询标志位或者通过中断的方式来鉴别。每个DMA通道在DMA传输过半、传输完成和传输错误时都会有相应的标志位,如果使能了该类型的中断后,则会产生中断。有关各个标志位的详细描述请参考DMA中断状态寄存器DMA_ISR的详细描述。

传输完成还分两种模式,是一次传输还是循环传输,一次传输很好理解,即是传输一次之后就停止,要想再传输的话,必须关断DMA使能后再重新配置后才能继续传输。循环传输则是一次传输完成之后又恢复第一次传输时的配置循环传输,不断的重复。具体的由DMA_CCR寄存器的CIRC循环模式位控制。

8.1    中断的不同

在循环模式下,每次DMA传输完成都会触发对应通道的中断服务函数;

⚠️但在非循环模式下,DMA的公共中断服务函数会调用__HAL_DMA_DISABLE_IT将中断失能,因此如果需要其始终起作用,就需要在中断服务函数中加上__HAL_DMA_ENABLE_IT。

8.2    对循环模式的支持

⚠️存储器到存储器的数据流向是不支持循环模式的。


9    其他特性

9.1    最大传输数

65535个字节。

在寄存器中,有一个寄存器存放当前剩余传输数目。

在非循环模式下,用户使能DMA并对该寄存器进行赋值N后,DMA会发送N个字节的数据,等N被倒数到0后,数据发送完毕。要再次发送就需要重新使能DMA并赋值N。

若在循环模式下N在减到0后自己就会循环回去N,从而循环发送。

9.2    内存到内存的传输

F1系列所有的DMA及DMA通道都支持内存到内存的传输。


10    相关HAL库函数


11    重要结构体


12    配置步骤

  • 非循环模式下,发送数据的准备步骤
    • __HAL_DMA_DISABLE(…);
    • 设置数量寄存器,如:dma_handle.Instance->CNDTR = len;
    • __HAL_DMA_ENABLE(…);
  • 查询通道状态的标志位
    • __HAL_DMA_GET_FLAG(&g_dma_handler, DMA_FLAG_TC1)
    • 这里的TC指的就是Transmit Complete,发送完成。
  • 清除通道状态的标志位
    • __HAL_DMA_CLEAR_FLAG(&g_dma_handler, DMA_FLAG_TC1)
  • 失能DMA
    • HAL_UART_DMAStop()
  • ⚠️⚠️⚠️__HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__)
    • 该宏函数用于将外设和DMA连接起来,让DMA知道处理哪个外设的数据,其中:
    • __HANDLE__为外设的句柄,__PPP_DMA_FIELD__为外设句柄中DMA句柄的名称(进入外设句柄的定义里能看到,如下图例子),__DMA_HANDLE__为DMA的句柄。
    • 需要注意的是:__HAL_LINKDMA宏函数的最后一个参数(即DMA句柄)无需加地址符,因为其内部就有了,因此调用的形式为:
      __HAL_LINKDMA(&adc_handle, DMA_Handle, dma_handle);
  • ⚠️⚠️⚠️HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
     
    • HAL_DMA_Start_IT函数的SrcAddress和DstAddress分别表示DMA数据的来源和目标地址,一般就是外设的DR寄存器或者是变量或数组。若是要传入数组的话会相对比较麻烦,见下图array是个数组:

       
      也可以这样转:
      (uint32_t)&array
    • 调用该函数时最好SrcAddress和DstAddress都强转成uint32_t再传入,像上图那样,否则会有警告。

13    注意事项

  • HAL_DMA_Init函数没有对应的MSP初始化函数,因此其时钟的开启代码要自己放好执行。
  • 如果有外设需要使用DMA,就要确认其使用的是DMA1还是DMA2,还要确认其使用的通道,具体就是查15.2里面的那个表就可以了。
  • 在设置DMA的参数(如传输数目CNDTR)时,需要确保DMA不在传输状态,常用while配合CCR的位0判断,或使用while配合DMA的传输完成TC标志做判断:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

以科研为本 创新突破的品牌理念 朵拉朵尚荣获2023年度影响力品牌奖

以科研为本 创新突破的品牌理念 朵拉朵尚荣获2023年度影响力品牌奖 随着国内美妆行业经过数十年的快速发展,已经形成了数千亿规模的产业链,在产业集聚、行业新技术不断涌现、产业链持续优化等背景下,美妆行业该如何通过科技创新,…

流量太炸裂了!一键AI替换视频人物,几分钟极速制作爆款视频!

目录 一、案例分析 二、制作教程 1.1、通义千问APP——角色扮演 1.2、Motionshop 1.3、Wonder Studio 1.4、Viggle 三、结束语 最近网上火了一种新玩法:用AI技术,一键就能把视频里的人物换成机器人或者任何你想要的角色。就像之前那些视频&#x…

二叉树高频题目-上-不含树型dp

二叉树高频题目-上-不含树型dp 题目1 : 二叉树的层序遍历 测试链接 : https://leetcode.cn/problems/binary-tree-level-order-traversal/ 思路 自己使用数组实现队列, 在队列中进行广度优先遍历先将根结点进队, 如果队列里还有东西, 按照队列大小进行循环, 让队列里的结点进…

创建一个最简单的FastAPI

如何生成一个最简单的 FastAPI 文件? FastAPI官方文档:https://fastapi.tiangolo.com/zh/tutorial/first-steps/ # -*- coding: utf-8 -*-""" file: main.py author: CSDN-北极的三哈 time: 2024/8/27 22:11 email:flymeawei163.com so…

【自动驾驶】控制算法(六)前馈控制与航向误差

写在前面: 🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝 个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。 🔍 本文系 清流君 原创之作&…

Python爬虫使用实例_1

Python爬虫使用实例 —— 续 IDE: Pycharm or Jupyter Notebook 6. 网易云歌榜 🥝 获取地址 记得把#/去掉就好,一定要记得,否则没用。 热歌榜的url是 https://music.163.com/discover/toplist?id3778678 ,同理可得其他榜的ur…

Java设计模式之单例模式详细讲解和案例示范

单例模式(Singleton Pattern)是Java设计模式中最简单但却非常实用的一种。它确保一个类只有一个实例,并提供一个全局的访问点。本文将通过电商交易系统为例,详细探讨单例模式的使用场景、常见问题及解决方案。 1. 单例模式简介 …

【LeetCode Cookbook(C++ 描述)】平衡二叉树

目录 平衡二叉树基础不同插入节点方式的不同旋转LL 型失衡RR 型失衡LR 型失衡RL 型失衡 删除操作删除节点为二叉树的叶子节点删除的节点只有左子树或者右子树删除的节点既有左子树又有右子树 LeetCode #110:Balanced Binary Tree 平衡二叉树递归法(自底向…

[C++番外] 抛异常

一、C语言的时候我们怎么判断错误的呢? C语言的错误处理机制: 终止程序,如assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。返回错误码,缺陷:需要程序员自己去查…

字典序排数

题目链接 字典序排数 题目描述 注意点 1 < n < 5 * 10^4 解答思路 参照题解使用dfs完成本题&#xff0c;需要注意的是结果不包含0&#xff0c;所以先遍历第一层&#xff08;1~9&#xff09;&#xff0c;再根据每个节点继续深搜&#xff0c;将访问到的节点按顺序添加…

测试开发面试题目汇总

之前因为面临换工作&#xff0c;所以通过一些渠道汇总了一些面试题目&#xff0c;然后加入了部分自己面试过程中遇到的问题&#xff0c;因此记录下来。文末有惊喜。 1. 项目经验 2. 测试的过程 3. 京东登录页面怎么测&#xff1f; 4. 如果一个普通用户&#xff0c;他的百度首…

EasyExcel动态映射Excel数据到任意实体类教程

在使用EasyExcel进行Excel导入时&#xff0c;我们经常需要将Excel中的数据映射到Java实体类中。如果Excel的列名是固定的&#xff0c;我们可以通过ExcelProperty("列名")注解直接在实体类中指定列名。但如果Excel的列名不固定&#xff0c;或者我们希望根据Excel的第一…

NS2582 同步升压双节锂电池充电管理 IC

1 特性  最大 2A 输出同步开关型升压充电器  升压效率可高达 90% 以上  内置电池短路 / 涓流 / 恒流 / 恒压模式  0.5% 电池恒压模式电压精度  支持 LED 充电状态指示  支持充电电流外部可调  支持输入适配器 DPM 功能  外置 EN 使能…

SQL语法:create、insert、update、

1.create创建表 创建表时&#xff0c;通常会有如下设置&#xff1a;主键、非空、取值唯一、使用自动增长等。 根据如图创建表名为userinfo的数据表&#xff1a; create table userinfo(id int not null primary key auto_increment,username varchar(50) not null unique,cre…

java框架第二课(Reflection反射机制)

一.关于反射 (1)使用场景介绍 平常我们写代码时&#xff0c;都是已知类名&#xff0c;类的属性&#xff0c;构造方法&#xff0c;其他方法等信息&#xff0c;然后根据类名new对象&#xff0c;这个过程称为正向操作(例如&#xff1a;有一个管理员类&#xff0c;有账号和密码属…

WEB渗透Win提权篇-BypassUAC

提权工具合集包&#xff08;免费分享&#xff09;&#xff1a; 夸克网盘分享 往期文章 WEB渗透Win提权篇-提权工具合集-CSDN博客 WEB渗透Win提权篇-RDP&Firewall-CSDN博客 WEB渗透Win提权篇-MSSQL-CSDN博客 WEB渗透Win提权篇-MYSQL-udf-CSDN博客 WEB渗透Win提权篇-Acc…

大模型基础环境部署之一:安装 Nvidia 的驱动(详细实操版)

一、系统准备前置条件 1、更新软件包列表 sudo apt-get update2、安装编译工具和依赖项 sudo apt-get install gcc sudo apt-get install make sudo apt-get install g注&#xff1a;如果在安装 g 时遇到错误消息&#xff1a;“***you do not appear to have libc header fi…

【C++ Primer Plus习题】6.2

问题: 解答: #include <iostream> #include <array> using namespace std;#define MAX 10int main() {array<float, MAX> arr;float sum0;float average0;int i 0;int count0;int bigger 0;for (i 0; i < MAX; i){cout << "请输入donation…

大数据技术之Flume 企业开发案例——聚合(7)

目录 聚合 1&#xff09;案例需求&#xff1a; 2&#xff09;需求分析 3&#xff09;实现步骤&#xff1a; 准备工作 创建 flume1-logger-flume.conf 创建 flume2-netcat-flume.conf 创建 flume3-flume-logger.conf 执行配置文件 聚合 1&#xff09;案例需求&#x…

华为eNSP:路由器子接口配置

一、拓扑图 二、 路由器配置 [R1]int g0/0/0.1#进入子接口 [R1-GigabitEthernet0/0/0.1]ip add 192.168.1.254 24#配置子接口地址 [R1-GigabitEthernet0/0/0.1]dot1q termination vid 10#标记终止的vid编号 [R1-GigabitEthernet0/0/0.1]arp broadcast enable #开启子接口的arp…