stm32f103c8t6学习笔记(学习B站up江科大自化协)-DMA

DMA简介

        ·DMA主要用于协助CPU完成数据转运的工作

        ·DMA,英文全称Direct Memory Access,DMA这个外设是可以直接访问STM32内部存储器的,包括运行内存SRAM,程序存储器flash和寄存器等等,DMA都有权限访问,所以DMA能完成数据转运的工作

        ·第二行的外设指的是外设寄存器,一般是外设的数据寄存器DR(Data Register),比如ADC的数据寄存器和串口的数据寄存器等等,存储器指的是运行内存sram和程序存储器flash,是存储变量数组和程序代码的地方。

        ·可配置的通道,指的是数据转运的路径,从一个地方转运到另一个地方需要占用一个通道,如果有多个通道进行转运,可以各转各的,互不干扰,

        ·如果DMA进行的是存储器到存储器的数据转运,比如想把flash里的数据转运到sram里去,那就需要软件触发,DMA会一股脑将数据以最快速度转运完成。

        如果DMA进行的是外设到存储器的数据转运,就不能一股脑转运。外设的数据转运是有时机的,需要使用硬件触发,比如转运ADC的数据,得等ADC每个通道AD转换完成之后,硬件触发一次DMA,之后DMA再进行转运,触发一次转运一次,数据才是正确的。

        存储器到存储器的转运一般使用软件触发,外设到存储器的转运一般使用硬件触发。特定的硬件触发意味着每个DMA的硬件触发源是不一样的,要使用某个外设的硬件触发源,就得使用他连接的那个通道,而不能任意选择通道

        ·c8t6这个芯片只有7个通道,没有DMA2

存储器映像

        ·ROM,只读存储器,是一种非易失性、掉电不丢失的存储器

ROM分为三块:
        第一块是程序存储器flash,也就是主闪存,用途是存储c语言编译后的代码,也就是下载程序的位置。运行程序一般是从主闪存里面开始运行。这一块存储器STM32分配的地址是0x0800 0000,起始地址,也就是第一个字节的地址0800,然后剩余字节的地址依次增长,每个字节都分配一个独一无二的地址,之后程序才能精准的访问这个寄存器。终止地址取决于他的容量,编到哪里,哪里就是终止地址。如果在软件里看到,某个数据的地址是0800开头的,一般可以确定为主闪存的数据。
        第二块和第三块也是掉电不丢失,不难看出这两块存储器的位置是在ROM区的最后面,实际上存储介质也是flash,只不过一般flash指的是主闪存flash,而不是指这两个区域。对于这两块区域的地址都是1FFF开头的。系统存储器的用途是存储bootloader,用于串口下载。bootloader一般是芯片出厂自动写入的,一般不允许修改。选项字节的存储器一般用于存储一些独立于程序代码的配置参数,位置是在ROM的最后面,下载程序可以不刷新选项字节的内容,这样选项字节的配置就可以保持不变,选项字节里主要存储的是flash的读保护和写保护,还有看门狗等等的配置。

        ·RAM,随机存储器,是一种    易失性,掉电    丢失的存储器
        2000开头的是ram区域,首先是运行内存sram,分配地址是0x2000 0000,用途是用于存储运行过程的临时变量,也就是在程序中定义变量、数组、结构体的地方,类比电脑的话,运行内存就是内存条。
        外设寄存器,地址是0x4000 0000,用途是存储各个外设的配置参数,也就是初始化各个外设最终读写的东西。外设寄存器也是存储器的一种,存储介质其实也是sram,不过一般习惯把运行内存叫做sram,外设寄存器直接叫做寄存器。
        内核外设寄存器,地址是0xE000 0000,用途是存储内核各个外设的配置参数,内核外设就是NVIC和systick,因为内核外设和其他外设不是一个厂家设计的,所以地址被分开。

DMA基本结构

        ·图中的外设寄存器和存储器(flash、sram)这两个部分是数据转运的两大站点,在STM32里,一般特指的是flash和sram,不包含外设寄存器。外设寄存器一般直接称作外设,寄存器也是存储器的一种,DMA的数据转运可以从外设到存储器,也可以从存储器到外设,具体转运方向有一个方向的参数可以进行控制。还有一种转运方式是从存储器到存储器,比如flash到sram或sram到sram这两种方式。由于flash是只读的,所以DMA不可以进行从sram到flash或flash到flash的转运操作。

        ·左右两边分别是外设和存储器的三个参数,要进行数据转运首先要指定从哪到哪,以及怎么转。所以外设和存储器都有三个参数
                第一个是起始地址,有外设端的起始地址和存储器端的起始地址,这两个参数决定了数据是从何来到何去,
                第二个参数是数据宽度,这个参数的作用是指定一次转运要按多大的数据宽度来进行,可以选择字节byte、半字halfword和字word。字节是八位,也就是一次转运一个uint8_t大小的数据,半字是uint16_t大小,字是uint32_t大小
                第三个参数是地址是否自增,这个参数的作用是指定一次转运完成之后,下一次转运是否要把地址移动到下一个地址去,相当于指针p++。比如ADC扫描模式,用DMA进行数据转运,外设地址是ADC_DR寄存器,寄存器这边显示地址是不需要自增的,原因是自增的话下次转运就跑到别的寄存器去了,但是存储器这边地址需要自增,每转运一次数据后都往后挪个坑,否则下次在转运的时候就会把上次的数据覆盖,这就是地址是否自增的作用。

        ·如果要进行存储器到存储器的数据转运,就需要把其中一个存储器的地址放在外设的站点。只要在外设起始地址里写入flash或sram的地址,那就会去flash和sram里面找数据。虽然这个站点叫做外设寄存器,仅是名字而已,并不代表这个地址只能写寄存器的地址,如果写flash就会去flash里面找,写sram就会去sram里面找,没有限制,甚至可以在外设站点写存储器的地址,存储器站点写外设的地址,然后方向参数反过来即可。

        ·下面有个传输计数器,用来指定总共需要转运几次,这个传输计数器是一个递减计数器,比如给他写一个5,那么DMA就只能进行5次数据转运,转运过程中,每转运一次计数器的数就会减1,当传输技术器减到0之后就不会进行数据转运,同时减到0之后,前边自增的地址也会恢复到起始的位置,以方便后边DMA开始新一轮的转运。

        ·在传输计数器的右边有一个自动重装器,作用是传输计数器减到0之后是否要恢复到最初的值,比如传输计数器初值给5,不使用自动重装器,那转运5次之后DMA就结束了,如果使用自动重装器,那重装5次计数器减到0之后就会立刻重装到初始值5。自动重装器决定了转运的模式,如果不重装那就是正常的单次模式,如果重装就是循环模式,如果想转运一个数组一般就是单次模式,转运一轮就结束;如果是ADC扫描+连续转换,为了配合ADC,DMA也需要使用循环模式。这个循环模式和ADC的连续模式相似,都用于指定一轮工作之后是否立刻开启下一轮工作。

        ·最下边是DMA的触发控制,触发决定了DMA是在什么时候进行转运。触发源有硬件触发和软件触发,具体选择哪个由M2M(Memory to Memory,由于2和two同音,意思是存储器到存储器)这个参数来决定。

        当给M2M时DMA会选择软件触发,这个软件触发并不是调用某一个函数触发一次,这个软件触发的逻辑是:以最快的速度不断地触发DMA,争取快速把传输寄存器清零,完成本轮转换。这里的软件触发和之前外部中断、ADC的软件触发不太一样,可以理解成连续触发,但是软件触发和循环模式不能同时使用,因为软件触发是为了将传输计数器清零,而循环模式是将其清零后自动重装,同时使用的话DMA停不下来。软件触发一般用于存储器到存储器之间的转运,是软件启动,不需要时机。

        当M2M位给0那就是使用硬件触发,硬件触发源可以选择ADC、串口、定时器等等,使用硬件触发的转运一般是和外设有关的转运,这些转运需要一定的时机,比如ADC转换完成、串口发送数据、定时时间到等等,当硬件达到这些时机时,传一个信号来触发DMA进行转运。

        ·开关控制,也就是DMA_CMD函数,当给DMA使能之后,DMA准备就绪,可以进行转运。DMA进行转运有几个条件:

        第一就是开关控制,DMA_Cmd必须使能

        第二就是传输计数器必须大于0

        第三就是触发源必须有触发信号,触发一次转运一次,传输计数器自减一次。当传输计数器等于0且没有自动重装时,此时无论是否触发DMA都不会进行转运,此时需要将DMA_Cmd给disable关闭DMA,再为传输计数器写一个大于0的数,在DMA_Cmd给enable开启DMA,DMA才能继续工作。

        注意:手册规定,写传输计数器时必须先关闭DMA再进行,不能在DMA开启时写传输计数器

DMA请求

        这张图是DMA1的请求映像,下面是DMA的7个通道,每个通道都有一个数据选择器,可以选择硬件触发或软甲触发

        ·图的左侧列外设请求信号,每个通道的硬件触发源都是不同的,如果需要使用ADC1来触发的话就需要选择通道1,如果需要定时器2来更新事件的话那就需要选择通道2。由于每个通道的硬件触发源不同,如果想使用某个硬件触发源的话,就必须使用其所在的通道,这是关于使用硬件触发的注意事项;如果使用软件触发的话通道可以任意选择,因为每个通道的软件触发都是一样的。
        ·图中通道1的硬件触发是ADC1,定时器2的通道3和定时器4的通道1,具体选择哪个触发源是根据对应的外设是否开启了DMA输出来决定的。比如要使用ADC1,那就会有个库函数叫ADC_DMACmd,必须使用这个库函数开启ADC1的这一路输出才有效;如果想使用定时器2的通道3,会有个TIM_DMACmd的函数进行DMA输出控制。关于这三个触发源使用哪个,取决于把哪个外设的DMA输出开启了,如果都开启了,那就变成了一个或门,三个硬件都可以进行触发,一般情况下只开启一个。
        ·最终7个触发源进入到仲裁器,进行优先级判断,最终产生内部的DMA1请求,优先级的判断类似于中断优先级。默认优先级是通道号越小优先级越高,可在程序中进行配置。
 

        这里的意思应该是,EN并不是数据选择器的控制位,而是选择数据寄存器是否工作,EN=0数据寄存器不工作,EN=1数据寄存器工作。软件触发后面跟着M2M位的意思是当M2M=1时选择软件触发。

数据宽度与对齐

        数据宽度与对齐,在前面的数据转运的两个站点都有一个数据宽度的参数,如果数据宽度都一样那就是一个一个正常的转运,如果数据宽度不一样,需要参考操作表格。表格中第一列是源端宽度,第二列是目标宽度,第三列是传输数目,当源端和目标都是8位时,转运第一步在源端的0位置读数据B0,在目标的0位置写数据B0,就是把这个B0从表格左边移到右边,接着就是把B1移动到右边,接着就是B2B3。源端是8位目标是16位,这个的操作是源端读B0,目标写入00B0,读B1写入00B1,如果目标的数据宽度比源端的数据宽度大,那就在目标前面多出来的空位补0。在8位转到32位同理,将前边空出来的都补0。当目标数据宽度比源端数据宽度小的时候,比如16位转8位,现象就是读B1和B0,只写入B0,读B3B2,只写入B2,写就是把多出来的高位舍弃,后边的也是类似操作。总结就是如果把小的数据转到大的里边就会补0,如果把大的数据转到小的里面高位就会舍弃。
 

DMA数据转运

        .使用DMA,进行存储器到存储器的数据转运,也就是把一个数组里的数据复制到另一个数组里。

        ·数据转运+DMA,将sram里面的数组DataA转运到另一个数组DataB中的配置方式如下,首先是外设站点和存储器站点的起始地址、数据宽度、地址是否自增这三个参数。在这个任务里外设数组(发送)应该填写DataA的数组的首地址,存储器地址(接收)给DataB数组的地址,数据宽度两个数组类型都是uint8_t,所以数据宽度都是按8位的字节传输,由图可见将数组A0转到数组B0,然后A1到B1等等,所以两个站点的地址都需要自增,都移动到下一个数据的位置,才能继续进行转运。如果左边自增右边补自增,那么最后只会有B0接收到A8的数据,如果左边不自增右边自增,最后B0到B8都是A0的数据,如果都不自增那么只有B0有A0的数据。由于将外设站点转运到存储器站点,方向参数需正向。数组中有7个数据,所以传输计数器给7,自动重装暂不需要。触发部分要使用软件触发,因为这是存储器到存储器的数据转运,无需等待时机,最后调用ADC_Cmd给DMA使能。这里的转运是复制转运,转运完成之后DataA的数据不会消失,仅是把DataA的数据复制到DataB的位置
 

DMA+数据多通道

        ·ADC扫描模式+DMA,左边是ADC扫描模式的执行流程,有七个通道,触发一次之后7个通道依次进行AD转换,然后转换结果放到ADC_DR寄存器里面。在每个单独的通道转换完成之后,进行一个DMA数据转运,并且目的的地址进行自增,防止数据被覆盖。外设地址写入ADC_DR这个寄存器的地址,存储器的地址可以在sram中定义一个数组ADValue,然后把ADValue的地址当做存储器的地址,之后数据宽度由于ADC_DR和sram数组都是uint16_t的数据,所以数据宽度都是16位的半字传输。在图中可见外设地址不自增存储器地址自增,传输方向是外设站点到存储器站点。传输通道有7个所以传输计数器设置为7。ADC如果是单次扫描,那么ADC的传输计数器可以不自动重装,转换一轮即停,如果ADC是连续扫描,可以使用自动重装,在ADC启动下一轮转换的时候,DMA也启动下一轮转运,ADC和DMA同步工作。ADC_DR的值是在ADC单个转换完成之后才有效的,所以DMA转运的时机,需要和ADC单个通道转换完成同步,所以ADC的触发要选择硬件触发。

        ·DMA最常用的用途就是配合ADC的扫描模式,因为ADC扫描模式有数据覆盖的特征,ADC对于DMA的需求非常强烈,其他的外设使用DMA将锦上添花,ADC没有的话功能会受到极大的限制。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP页面如何实现设置独立访问密码

PHP网页如果需要查看信息必须输入密码,验证后才可显示出内容的代码如何实现? 对某些php页面设置单独的访问密码,如果密码不正确则无法查看内容,相当于对页面进行了一个加密。 如何实现这个效果,详细教程可以参考:PHP页面如何实现…

基于react native的自定义轮播图

基于react native的自定义轮播图 效果示例图示例代码 效果示例图 示例代码 import React, {useEffect, useRef, useState} from react; import {Animated,PanResponder,StyleSheet,Text,View,Dimensions, } from react-native; import {pxToPd} from ../../common/js/device;c…

【Linux】进程状态(R运行状态、S睡眠状态、D磁盘休眠状态、T停止状态、X死亡状态)

目录 01.运行状态 02.睡眠状态 03.磁盘睡眠状态 04.停止状态 05.死亡状态 进程的状态会随着操作系统的调度和外部事件的发生而不断地发生转换。例如,一个新创建的进程经过初始化后会进入就绪态,等待被调度执行;当调度器分配处理器资源给…

Windows直接运行python程序

Windows直接运行python程序 一、新建bat脚本二、新建vbs脚本 一、新建bat脚本 新建bat批处理脚本,写入以下内容 echo off call conda activate pytorch python app.pyecho off:在此语句后所有运行的命令都不显示命令行本身,但是本身的指令是…

Android: Gradle 命令

一、查看整个项目依赖传递关系 x.x.x (*) 该依赖已经有了,将不再重复依赖。x.x.x -> x.x.x 该依赖的版本被箭头所指的版本代替。x.x.x -> x.x.x(*) 该依赖的版本被箭头所指的版本代替,并且该依赖已经有了,不再重复依赖。 1. gradlew ap…

申请即管控、差补自动算......企业差旅,想怎么省就怎么省

3月开始,企业商旅行为逐步升温。但管控难度也随之而来: ● 同时段、同起终地,预订机、火。企业支付后,总忘记取消未使用行程; ● 同天预订不同城市酒店,非入住酒店经常无法免费取消; ● 短途差旅,依然按习惯预订机票...... 为了提高效率,“出一趟差,办多项事”成了很多企业…

隐语笔记2 —— 隐私计算开源如何助力数据要素流通

数据生命周期 数据流转链路主要包括:采集、存储、加工、使用、提供、传输 数据要素外循环是构建数据要素市场的核心 数据外循环中的信任焦虑 三个代表性问题: 不可信内部人员不按约定使用用户隐私泄漏 数据权属问题 解决方案:从主体信任…

耳目一新的滑块版登录注册界面~

又到了毕业季,大家做毕设的时候总会参考已有的案例,不过大多产品的样式非常单一雷同。本帖博主给大家分享一个比较别树一帜的登录界面,如下: 如果没有账号,点击“去注册”,则会产生如下的效果: …

金融投贷通(金融投资+贷款通)项目准备

金融投贷通(金融投资贷款通)项目准备 专业术语投资专业术语本息专业术语还款专业术语项目介绍三个子系统技术架构核心流程发布借款标投资业务 项目实施测试流程测试步骤 专业术语 投资专业术语 案例:张三借给李四5W,约定期满1年后…

特斯拉铺路 小米SU7稳了

文 | AUTO芯球 作者 | 李逵 我把特斯拉的销售拉黑了 拉完又后悔了 因为我欠他一个人情啊 具体怎么回事 看完你就会明白了 今天一大早 特斯拉的销售就发信息给我 说从4月1号开始 特斯拉就要涨价了 我以前去看的Model Y 要提价5000块 而且之前的补贴 什么保险补贴、…

844. 走迷宫 典bfs

AC代码&#xff1a; #include<algorithm> #include<iostream> #include<cstring> #include<queue> #include<algorithm> #include<cmath> using namespace std; const int N 110;int mp[N][N]; int sx,sy; bool vis[N][N]; struct node{i…

TCP重传机制详解——02SACK

文章目录 TCP重传机制详解——02 SACKSACK是什么&#xff1f;为什么要有SACK&#xff1f;实际场景抓包具体显示信息流程 实战抓包讲解SACK关闭场景下&#xff0c;三次重复ACK后会快速重传SACK打开但是不携带SACK块信息场景下&#xff0c;三次重复ACK也不会快速重传SACK打开并且…

mysql分页查询多用GitCode平台

目录 一、在GitCode平台AI搜索结果&#xff08;这个更优&#xff09; 二、在百度搜索输入“mysql Java分页查询”的输出结果&#xff1a; 三、推荐的文章 四、GitCode的使用 1&#xff09;如搜索jdk11可以直接下载jdk11的包 2&#xff09;搜索开源项目 3&#xff09;如搜…

修改Jupyter Notebook的默认路径,以及在PowerShell中自定义其启动路径

修改Jupyter Notebook的默认路径&#xff0c;以及在PowerShell中自定义其启动路径 设置 Jupyter Notebook 配置文件&#xff0c;修改默认路径要在PowerShell中设置自定义的启动脚本&#xff0c;以确保Jupyter Notebook能够自动定位到当前路径设置后的效果 在使用Jupyter Notebo…

API网关-Apisix路由配置教程(数据编辑器方式)

文章目录 前言一、端口修改1. apisix 端口修改2. dashboard 端口修改3. 登录密码修改 二、常用插件介绍1. 常用转换插件1.1 proxy-rewrite插件1.1.1 属性字段1.1.2 配置示例 2. 常用认证插件2.1 key-auth插件2.1.1 消费者端字段2.1.2 路由端字段2.1.3 配置示例 2.2 basic-auth插…

37、Linux中Xsync数据同步备份工具

37、Linux中Xsync数据同步备份工具 一、介绍二、配置集群hostname三、修改xsync文件四、赋权五、安装Rsync六、验证一七、配置免密登录1、生成rsa密钥2、copy机器自身公钥到目标机器3、.ssh/文件目录赋权 八、验证二 ⚠️ 注&#xff1a;本文全程在普通用户下操作&#xff0c;…

基于RK3588多can口多串口机器人全功能板

RK3588机器人控制器有五大技术优势 1. 内置多种功能强大的嵌入式硬件引擎&#xff0c;支持8K60fps 的 H.265 和 VP9 解码器、8K30fps 的 H.264 解码器和 4K60fps 的 AV1 解码器&#xff1b;支持 8K30fps 的 H.264 和H.265 编码器&#xff0c;高质量的 JPEG 编码器/解码器&…

网络探测工具Nmap介绍

1. Nmap简介 Nmap是一款用于网络发现和安全审计的网络安全工具。可用于列举网络主机清单、管理服务升级调度、监控主机、监控主机服务运行状况、检测目标主机是否在线和端口开放情况、侦测运行的服务类型及版本信息、侦测操作系统与设备类型等。 2. 命令大纲 3. 命令详细介绍…

基于 Linux 的更新版 MaxPatrol VM 可扫描 Windows

&#x1f47e; MaxPatrol VM 2.1 是俄罗斯唯一一款可以安装在 Linux 上并以审计和五重测试模式扫描 Windows 主机&#xff08;甚至是旧版本&#xff09;的漏洞管理产品。 让我们告诉你更新后的 MaxPatrol VM 还有哪些有用的功能&#xff1a; 1. 由于采用了新的数据存储模式&a…

【物联网开源平台】tingsboard安装与编译

别看这篇了&#xff0c;这篇就当我的一个记录&#xff0c;我有空我再写过一篇&#xff0c;编译的时候出现了一个错误&#xff0c;然后我针对那一个错误执行了一个命令&#xff0c;出现了绿色的succes,我就以为整个tingsboard项目编译成功了&#xff0c;后面发现的时候&#xff…