STM32单片机DMA存储器详解

news2024/11/26 11:53:19

文章目录

1. DMA概述

2. 存储器映像

3. DMA框架图

4. DMA请求

5. 数据宽度与对齐

6. DMA数据转运

7. ADC扫描模式和DMA

8. 代码示例


1. DMA概述

DMA(Direct Memory Access)可以直接访问STM32内部的存储器,DMA是一种技术,允许外设和存储器之间直接传输数据,而无需通过CPU进行数据搬运。这种技术大大提高了数据传输效率,减少了CPU的负担,使CPU能够专注于其他计算任务。

DMA可以提供外设(外设寄存器,⼀般是外设的数据寄存器DR(Data Register),比如ADC的数据寄存器,串口的数据寄存器)和存储器(运行内存(SRAM)和程序存储器(Flash)是存储变量数组和程序代码的地方)或者存储器与存储器之间的高速数据传输,非常适合用于需要高带宽数据流的应用,例如音频数据传输、图像处理等。

STM32系列一共有12个独立可配置的通道: DMA1(7个通道), DMA2(5个通道)。但是在STM32F103C8T6中,只有一个个DMA1控制器。每个通道都可以配置为不同的外设或存储器数据传输。

例如:DMA1的通道1可以配置为ADC(模数转换器)数据传输通道,DMA1的通道2可以配置为USART(通用同步/异步收发器)数据传输通道等。

每个通道都支持软件触发和特定的硬件触发,存储器到存储器的数据转运,⼀般用软件触发,外设到存储器的转运⼀般用硬件触发。

  • 软件触发:可以通过编程控制DMA的启动,例如在需要传输数据时,通过软件命令触发DMA操作。
  • 硬件触发:一些外设(例如ADC转换完成、USART接收到数据)可以配置为在特定事件发生时自动触发DMA进行数据传输。这种硬件触发机制可以进一步提高系统的实时性能。

2. 存储器映像

类型起始地址存储器用途
ROM

0x0800 0000

程序存储器Flash

存储C语言编译后的程序代码。这个区域主要用于存储用户的应用程序代码,通常是通过编程器或BootLoader进行烧录。

0x1FFF F000

系统存储器

存储BootLoader,用于串口下载。这个区域包含了STM32内部的系统启动加载程序,用户可以通过串口等方式下载新程序。

0x1FFF F800

选项字节

存储一些独立于程序代码的配置参数。这些配置参数包括读保护、写保护等安全设置。
RAM

0x2000 0000

运行内存SRAM

存储运行过程中的临时变量。这个区域用于程序运行时的堆栈、全局变量、动态分配的内存等。

0x4000 0000

外设寄存器

存储各个外设的配置参数。这个区域用于映射STM32的各个外设的寄存器地址,程序通过访问这些地址来配置和控制外设。

0xE000 0000

内核外设寄存器

存储内核各个外设的配置参数。这个区域主要包含Cortex-M3核心的系统控制寄存器、调试接口等。

计算机系统的五大组成部分

  1. 运算器:负责执行计算和逻辑操作,是计算机进行数据处理的主要部件。
  2. 控制器:负责指挥和协调计算机各部分的工作,控制指令的执行顺序和操作。
  3. 存储器:用于存储数据和程序,是计算机的重要组成部分,分为主存储器和辅助存储器。
  4. 输入设备:用于将外部信息输入到计算机中,如键盘、鼠标、扫描仪等。
  5. 输出设备:用于将计算机处理结果输出到外部,如显示器、打印机等。

存储器的分类

存储器主要分为两大类:只读存储器(ROM)和随机存储器(RAM)。

ROM(只读存储器)

ROM是一种非易失性存储器,即使在断电后,其内容也不会丢失。可以分为以下几种:

  • 程序存储器(Flash):主要用于存储经过编译的程序代码。一般情况下,程序从主闪存开始运行。
  • 系统存储器:存储启动加载程序(BootLoader),该程序通常在芯片出厂时写入,不允许用户修改。
  • 选项字节:用于存储配置数据,如Flash的读写保护设置和看门狗配置等。尽管它们也属于ROM范畴,但其存储介质也是Flash。

RAM(随机存储器)

RAM是一种易失性存储器,断电后其内容会丢失。主要分为以下几种用途:

  • 运行内存(SRAM):用于存储程序中定义的变量、数组和结构体等临时数据。
  • 外设寄存器:用于存储初始化各个外设的配置数据,以及外设运行时读写的数据。这些寄存器的存储介质也是SRAM。
  • 内核外设:例如NVIC(中断控制器)和SysTick(系统定时器)的存储器,这些也是用来控制和管理计算机的外设功能。

3. DMA框架图

 左上角是Cortex-M3内核,其中包含了CPU和内核外设,其他部分可以视为存储器。Flash是主闪存,SRAM是运行内存,各个外设可以看成寄存器,它们也是一种SRAM存储器。寄存器是一种特殊的存储器,CPU可以像读写内存一样对寄存器进行操作。同时,寄存器的每一位连接着控制外设电路的导线,用于控制引脚的高低电平、导通和断开等。寄存器是软件与硬件的桥梁,通过读写寄存器,软件实际上在控制硬件。

为了高效管理存储器,设计了一个总线矩阵。总线矩阵的左边是主动单元(具有存储器访问权),右边是被动单元(只能被动读取)。内核中有DCode总线(专门访问Flash)和系统总线(访问其他存储器)。DMA作为主动单元,也需要总线访问权,有自己的总线(DMA1和DMA2),它们分别有7个和5个通道,负责设置数据的源地址和目标地址。仲裁器决定通道的优先级,确保公平访问。

在总线矩阵中,如果DMA和CPU同时访问同一目标,DMA会暂停CPU的访问,但总线仲裁器会保证CPU得到一半的总线带宽。DMA本身也有自己的配置寄存器,连接在AHB总线上,因此DMA既是主动单元也可以作为被动单元接受访问。DMA请求是硬件触发信号,用于在ADC转换完成或串口接收到数据时,触发DMA进行数据转运。

Flash是ROM的一种,通过总线直接访问时,无论是CPU还是DMA,都只能读取数据,不能写入。如果DMA的目标地址是Flash区域,会导致转运错误。写入Flash需要通过接口控制器,先擦除再写入数据。

DMA的数据转运可以从外设到存储器,也可以从存储器到外设,还可以在存储器之间进行。每个站点(外设或存储器)有三个参数:

  1. 起始地址:包括外设端的起始地址和存储器端的起始地址,决定数据从哪里来,到哪里去。
  2. 数据宽度:指定一次转运的数据宽度,可以是字节(8位),半字(16位),或字(32位)。例如,ADC的数据为16位(uint16_t),因此应选择半字。
  3. 地址自增:决定每次转运后,地址是否移动到下一个位置。例如,在ADC扫描模式下,外设地址不需自增,而存储器地址需要自增,以防止数据覆盖。

传输计数器与自动重装器

  • 传输计数器:指定总共转运的次数,是一个自减计数器。例如,设置为5,则DMA只能转运5次,每次转运后计数器减1。当计数器减到0后,DMA停止转运,并恢复到起始地址。
  • 自动重装器:决定计数器减到0后是否自动恢复到初始值。如果使用自动重装器,DMA会在计数器减到0后自动重装初始值,实现循环模式;否则是单次模式。

DMA触发控制

DMA的触发源有硬件触发和软件触发,通过M2M参数选择。当M2M为1时,使用软件触发,DMA以最快速度连续不断地触发,直到传输计数器清0。软件触发和循环模式不能同时使用,因为软件触发清零后不重装,循环模式清零后自动重装。

当M2M为0时,使用硬件触发,常用于与外设有关的转运。例如,ADC转换完成、串口接收到数据或定时时间到时,硬件触发DMA进行转运。

DMA启用条件

DMA准备进行转运的条件包括:

  1. 开关控制:DMA_Cmd必须使能。
  2. 传输计数器:必须大于0。
  3. 触发源:必须有触发信号。每次触发,传输计数器自减1。当计数器等于0且无自动重装时,DMA停止转运。此时,需要禁用DMA(DMA_Cmd给DISABLE),重设传输计数器,然后重新启用DMA(DMA_Cmd给ENABLE),才能继续工作。写传输计数器时,必须先关闭DMA,再进行设置。

4. DMA请求

 这张图显示了DMA1的请求映像,其中包括DMA的7个通道。每个通道都有一个数据选择器,可以选择硬件触发或软件触发。左边列出了硬件触发源,每个通道的硬件触发源是不同的。例如:

  • 若要选择ADC1来触发,则必须选择通道1。
  • 若要选择TIM2的更新事件来触发,则必须选择通道2。

每个通道的硬件触发源是固定的,所以要使用某个硬件触发源,就必须使用其对应的通道。而如果使用软件触发,则可以任意选择通道。

硬件触发与软件触发

  • 硬件触发:每个硬件触发源对应固定的通道。例如,使用ADC1作为触发源时,需要调用库函数ADC_DMACmd来开启ADC1的DMA输出。同理,使用定时器2的通道3时,需要使用TIM_DMACmd函数来控制DMA输出。具体选择哪个触发源,取决于你开启了哪个外设的DMA输出。

  • 软件触发:软件触发时,通道选择是任意的,不受硬件触发源的限制。

优先级仲裁

这7个触发源进入仲裁器,进行优先级判断,最终产生内部的DMA1请求。默认情况下,通道号越小,优先级越高。但是,这个优先级可以在程序中进行配置。

5. 数据宽度与对齐

第一列表示源端宽度,第二列表示目标宽度,第三列表示传输数量。以下是不同情况下的操作:

源端宽度和目标宽度都是8位

  • 源端0位置读数据B0,目标0位置写数据B0。

  • 依次将B1、B2、B3从源端挪到目标端。

源端宽度8位,目标宽度16位

  • 源端读取B0,目标写入00B0。

  • 源端读取B1,目标写入00B1,依此类推。

  • 目标宽度大于源端宽度时,目标数据前面多出来的空位补0。

源端宽度8位,目标宽度32位

  • 类似地,源端读取8位数据,目标写入32位数据时,前面空位补0。

源端宽度16位,目标宽度8位

  • 源端读取B1B0,只写入B0,舍弃高位B1。

  • 源端读取B3B2,只写入B2,舍弃高位B3。

总结

  • 当目标宽度大于源端宽度时,目标数据前面空位补0。

  • 当目标宽度小于源端宽度时,舍弃多余的高位数据。

  • 当源端和目标宽度相同时,数据直接传输,无需额外处理。

6. DMA数据转运

将SRAM中的数组DataA转运到另一个数组DataB中,参数配置如下:

  • 外设地址:DataA数组的首地址

  • 存储器地址:DataB数组的首地址

  • 数据宽度:两个数组的类型都是uint8_t,所以数据宽度为8位(字节)传输

  • 地址自增

    • 如果两个站点的地址都自增,转运完成后,DataB数组的所有数据将与DataA数组相同。
    • 如果源地址(DataA)不自增,而目标地址(DataB)自增,转运完成后,DataB的所有数据都会等于DataA[0]。
    • 如果源地址(DataA)自增,而目标地址(DataB)不自增,DataB[0]将等于DataA的最后一个数,DataB的其他数据保持不变。
    • 如果两个地址都不自增,DataA[0]转到DataB[0],其他数据不变。
  • 方向参数:从外设站点(DataA)转运到存储器站点(DataB)。

  • 传输计数器:设置为7,不需要自动重装。

  • 触发选择:选择软件触发。

最后,调用DMA_Cmd使能DMA,转运7次后,传输计数器减到0,DMA停止,转运完成。需要注意的是,这种数据转运是一种复制转运,转运完成后DataA的数据不会消失。

7. ADC扫描模式和DMA

左边展示的是ADC扫描模式下的转运流程。每次触发后,7个通道依次进行AD转换,并将转换结果存放在ADC_DR寄存器中。每个通道转换完成后,进行一次DMA数据转运,同时自增目标地址,防止数据覆盖。

DMA配置

  1. 外设地址:设置为ADC_DR寄存器的地址。
  2. 存储器地址:在SRAM中定义一个数组ADValue,并将其地址作为存储器地址。
  3. 数据宽度:因为ADC_DR和SRAM数组都使用uint16_t数据类型,数据宽度设置为16位(半字)传输。
  4. 地址自增
    • 外设地址不自增。
    • 存储器地址自增。
  5. 传输方向:从外设站点(ADC_DR)到存储器站点(ADValue数组)。
  6. 传输计数器:设置为7,与通道数量相同。
  7. 自动重装:根据ADC的配置决定。
    • 如果ADC是单次扫描,DMA传输计数器不需要自动重装,完成一次转换后停止。
    • 如果ADC是连续扫描,DMA可以选择自动重装,在ADC启动下一轮转换时,DMA也启动下一轮转运,使ADC和DMA同步工作。
  8. 触发选择:选择ADC的硬件触发。ADC扫描模式在单个通道完成转换后,不会置任何标志位或产生中断,但会产生DMA请求,触发DMA转运。

8. 代码示例

STM32基于DMA数据转运和AD多通道

STM32基于DMA数据转运和AD多通道-CSDN博客

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

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

相关文章

C++ | Leetcode C++题解之第162题寻找峰值

题目&#xff1a; 题解&#xff1a; class Solution { public:int findPeakElement(vector<int>& nums) {int n nums.size();// 辅助函数&#xff0c;输入下标 i&#xff0c;返回一个二元组 (0/1, nums[i])// 方便处理 nums[-1] 以及 nums[n] 的边界情况auto get …

【漏洞复现】泛微OA E-Cology ln.FileDownload 任意文件读取漏洞

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

Debian12的#!bash #!/bin/bash #!/bin/env bash #!/usr/bin/bash #!/usr/bin/env bash

bash脚本开头可写成 #!/bin/bash , #!/bin/env bash , #!/usr/bin/bash , #!/usr/bin/env bash #!/bin/bash , #!/usr/bin/bash#!/bin/env bash , #!/usr/bin/env bash Debian12的 /bin 是 /usr/bin 的软链接, /sbin 是 /usr/sbin 的软链接, (Debian12默认没有ll命令,用的ls …

网络安全:数据库安全性

文章目录 网络安全&#xff1a;数据库安全性引言数据库安全性的重要性常见的数据库安全威胁数据库安全性的最佳实践数据加密访问控制审计和监控 结语 网络安全&#xff1a;数据库安全性 引言 在前两篇文章中&#xff0c;我们讨论了SQL注入的概念和防范措施。本篇文章将聚焦于…

5216万!国内自动化巨头,拟剥离旗下子业务

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 近日&#xff0c;中控技术发布公告称&#xff0c;为进一步优化资产结构和产业布局&#xff0c;提升公司核心竞争力&#xff0c;公司拟将其全资子…

Python | Leetcode Python题解之第162题寻找峰值

题目&#xff1a; 题解&#xff1a; class Solution:def findPeakElement(self, nums: List[int]) -> int:n len(nums)# 辅助函数&#xff0c;输入下标 i&#xff0c;返回 nums[i] 的值# 方便处理 nums[-1] 以及 nums[n] 的边界情况def get(i: int) -> int:if i -1 or…

canvas实现画布拖拽效果 适配Uniapp和Vue (开箱即用)

需求:我司是做AIGC项目最近和地铁项目有关需要实现海报效果图&#xff0c;并且需要使用画布拖拽和修改上传删除等等功能 当时连续加班花了10个工作日搓出来 实现挺简单的但是Canvas数据处理还是挺麻烦的 大概功能如图下 首先我们需要引入Fabric.js 这个库封装好了原生的Canva…

如何实现element表格合并行?

前两天我一个朋友咨询我element表格合并行的问题,他研究了很久,已经开始怀疑是不是element UI出现了bug,然后跟我一阵沟通,最终解决了问题,他的问题在于他把事情想复杂了,接下来我们一起来看一下这个经典“案例”,很多人真的很有可能走入这个误区,当然老鸟就不用看了,…

Pyqt QCustomPlot 简介、安装与实用代码示例(二)

目录 前言实用代码示例彩色图演示散点像素图演示实时数据演示多轴演示对数轴演示 结语 所有文章除特别声明外&#xff0c;均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 nixgnauhcuy’s blog&#xff01; 如需转载&#xff0c;请标明出处&#xff01; 完整代码我已经上传到…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 内存访问热度分析(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

《EDA技术》十六选一数据选择器实验报告

摘 要&#xff1a; 本实验通过Quartus软件完成对十六选一数据选择器的四种VHDL程序&#xff0c;分别为if;case;when else;when select四种方式&#xff0c;实现波形图的生成。同时&#xff0c;加深对VHDL语言的理解和使用多种方式完成任务的能力&#xff0c;提高实验操作能力。…

[WTL/Win32]_[中级]_[MVP架构在实际项目中应用的地方]

场景 在开发Windows和macOS的界面软件时&#xff0c;Windows用的是WTL/Win32技术&#xff0c;而macOS用的是Cocoa技术。而两种技术的本地语言一个主打是C,另一个却是Object-c。界面软件的源码随着项目功能增多而增多&#xff0c;这就会给同步Windows和macOS的功能造成很大负担…

vue:对三种获取更新后的dom的方式进行分析

一、问题分析 由于vue的异步更新机制&#xff0c;我们在同步代码中是无法获取到更新后的dom的信息的 针对这个问题&#xff0c;我们有三种解决方案获取更新后的dom: 1.nextTick() 2.setTimeout() 3.在微任务中获取 因为更新是在同步任务结束后&#xff0c;执行微任务之前…

Java项目常用包的分层和作用

一个好的Java项目要有好的分层&#xff0c;不仅简洁明了&#xff0c;而且降低代码的耦合度&#xff0c;方便维护和升级。 web层 在Java Web应用程序中&#xff0c;Web层通常指的是处理HTTP请求和响应的层次&#xff0c;它直接与客户端&#xff08;通常是Web浏览器&#xff09…

【idea】gradle多模块构建项目内存溢出终止问题解决

背景 idea构建多模块项目&#xff0c;构建报错 Daemon is stopping immediately JVM garbage collector thrashing and after running out of JVM memory 解决 进到下图目录下 在文件管理中进入上面目录添加gradle.properties文件&#xff0c;内容如下 org.gradle.jvmargs-…

学校校园考场电子钟,同步授时,助力考场公平公正-讯鹏科技

随着教育技术的不断发展&#xff0c;学校对于考场管理的需求也日益提高。传统的考场时钟往往存在时间误差、维护不便等问题&#xff0c;这在一定程度上影响了考试的公平性和公正性。为了解决这些问题&#xff0c;越来越多的学校开始引入考场电子钟&#xff0c;通过同步授时技术…

【深度学习】GPT-2,Language Models are Unsupervised Multitask Learners,【语言建模】

论文&#xff1a;https://d4mucfpksywv.cloudfront.net/better-language-models/language_models_are_unsupervised_multitask_learners.pdf 文章目录 摘要引言方法2.1 训练数据集2.2 输入表示2.3 模型3. 实验3.1 语言建模3.2 Children’s Book Test3.3 LAMBADA3.4 Winograd Sc…

兼容MacOS和FreeBSD软件包的开源ravynOS操作系统

ravynOS 是一个新型的操作系统项目&#xff0c;致力于在 x86-64&#xff08;终极目标是同时实现 ARM&#xff09;平台上提供与 macOS 类似的体验和兼容性。它基于坚若磐石的 FreeBSD、现有的开源代码和锦上添花的新代码构建。 主要设计目标&#xff1a; 与 macOS 应用程序的源…

python基础语法 002 - 4 字符串

1 字符串 字符串&#xff1a;引号括起来的数据类型 # 双引号 a "yuze wang"# 单引号 a ’yuze wang‘# 三引号 a ’‘’yuze‘‘’ a """yuze"""注意&#xff1a;所有格式表示都是半角&#xff0c;全角会报错 1.1 引号表示 …

C++及cmake语法介绍

c/cmake学习 文章目录 c/cmake学习1. c1.1 基本模型1.1.1 for循环1.1.2 main函数1.1.2 带参数函数编译函数 2. CMAKE2.1 相关命令2.1.1 编译基本命令2.1.2 动态库静态库编译2.1.3 消息输出2.1.4 cmake变量常见参数1. 设置构建类型2. 设置编译器标志3. 指定编译器4. 设置安装路径…