stm32 文件系统dma大小_STM32 DMA使用详解

DMA部分我用到的相对简单,当然,可能这是新东西,我暂时还用不到它的复杂功能吧。下面用问答的形式表达我的思路。

DMA有什么用?

直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。

有多少个DMA资源?

有两个DMA控制器,DMA1有7个通道,DMA2有5个通道。

数据从什么地方送到什么地方?

外设到SRAM(I2C/UART等获取数据并送入SRAM);

SRAM的两个区域之间;

外设到外设(ADC读取数据后送到TIM1控制其产生不同的PWM占空比);

SRAM到外设(SRAM中预先保存的数据送入DAC产生各种波形);

……还有一些目前还搞不清楚的。

DMA可以传递多少数据?

传统的DMA的概念是用于大批量数据的传输,但是我理解,在STM32中,它的概念被扩展了,也许更多的时候快速是其应用的重点。数据可以从1~65535个。

直接存储器存取(Direct Memory Access,DMA)是计算机科学中的一种内存访问技术。它允许某些电脑内部的硬体子系统(电脑外设),可以独立地直接读写系统存储器,而不需绕道 CPU。在同等程度的CPU负担下,DMA是一种快速的数据传送方式。它允许不同速度的硬件装置来沟通,而不需要依于 CPU的大量中断请求。【摘自Wikipedia】

现在越来越多的单片机采用DMA技术,提供外设和存储器之间或者存储器之间的高速数据传输。当 CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器 来实行和完成。STM32就有一个DMA控制器,它有7个通道,每个通道专门用来管理一个或多个外设对存储器访问的请求,还有一个仲裁器来协调各个DMA请求的优先权。

DMA 控制器和Cortex-M3核共享系统数据总线执行直接存储器数据传输。当CPU和DMA同时访问相同的目标(RAM或外设)时,DMA请求可能会停止 CPU访问系统总线达若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线(存储器或外设)带宽。

在发生一个事件后,外设发送一个请求信号到DMA控制器。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问外设的时候,DMA控制器立即发送给外设一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。如果发生更多的请求时,外设可以启动下次处理。

总之,每个DMA传送由3个操作组成:

1. 从外设数据寄存器或者从DMA_CMARx寄存器指定地址的存储器单元执行加载操作。

2. 存数据到外设数据寄存器或者存数据到DMA_CMARx寄存器指定地址的存储器单元。

3. 执行一次DMA_CNDTRx寄存器的递减操作。该寄存器包含未完成的操作数目。

仲裁器根据通道请求的优先级来启动外设/存储器的访问。优先级分为两个等级:软件(4个等级:最高、高、中等、低)、硬件(有较低编号的通道比拥有较高编号的通道有较高的优先权)。

可以在DMA传输过半、传输完成和传输错误时产生中断。

STM32中DMA的不同中断(传输完成、半传输、传输完成)通过“线或”方式连接至NVIC,需要在中断例程中进行判断。

进行DMA配置前,不要忘了在RCC设置中使能DMA时钟。STM32的DMA控制器挂在AHB总线上。

DMA总共有7个通道,各个通道的DMA映射关系如下:

外设的事件连接至相应DMA通道,每个通道均可以通过软件触发实现存储器内部的DMA数据传输(M2M模式)

Tips:库2.0中函数RCC_AHBPeriphClockCmd的参数由“RCC_AHBPeriph_DMA”改成“RCC_AHBPeriph_DMA1”(如果是DMA1控制器的话)。

DMA的传输标志位(CHTIFx、CTCIFx、CGIFx)由硬件设置为“1”,但需要软件清零,在中断服务程序中清除。当CGIFx(全局中断标志位)清零后,CHTIFx 和 CTCIFx均清零。

过程:怎样启用DMA?首先,众所周知的是初始化,任何设备启用前都要对其进行初始化,要对模块初始化,还要先了解该模块相应的结构及其函数,以便正确的设置;由于DMA较为复杂,我就只谈谈DMA的基本结构和和常用函数,这些都是ST公司提供在库函数中的。

1、 下面代码是一个标准DMA设置,当然实际应用中可根据实际情况进行裁减:

DMA_DeInit(DMA_Channel1);

上面这句是给DMA配置通道,根据ST提供的资料,STM3210Fx中DMA包含7个通道(CH1~CH7),也就是说可以为外设或memory提供7座“桥梁”(请允许我使用桥梁一词,我觉得更容易理解,哈哈,别“拍砖”呀!);

DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

上面语句中的DMA_InitStructure是一个DMA结构体,在库中有声明了,当然使用时就要先定义了;DMA_PeripheralBaseAddr是该结构体中一个数据成员,给DMA一个起始地址,好比是一个buffer起始地址,数据流程是:外设寄存器à DMA_PeripheralBaseAddàmemory中变量空间(或flash中数据空间等),ADC1_DR_Address是我定义的一个地址变量;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue;

上面这句很显然是DMA要连接在Memory中变量的地址,ADC_ConvertedValue是我自己在memory中定义的一个变量;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

上面的这句是设置DMA的传输方向,就如前面我所说的,DMA可以双向传输,也可以单向传输,这里设置的是单向传输,如果需要双向传输:把DMA_DIR_PeripheralSRC改成DMA_DIR_PeripheralDST即可。

DMA_InitStructure.DMA_BufferSize = 2;

上面的这句是设置DMA在传输时缓冲区的长度,前面有定义过了buffer的起始地址:ADC1_DR_Address ,为了安全性和可靠性,一般需要给buffer定义一个储存片区,这个参数的单位有三种类型:Byte、HalfWord、word,我设置的2个half-word(见下面的设置);32位的MCU中1个half-word占16 bits。

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

上面的这句是设置DMA的外设递增模式,如果DMA选用的通道(CHx)有多个外设连接,需要使用外设递增模式:DMA_PeripheralInc_Enable;我的例子里DMA只与ADC1建立了联系,所以选用DMA_PeripheralInc_Disable

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

上面的这句是设置DMA的内存递增模式,DMA访问多个内存参数时,需要使用DMA_MemoryInc_Enable,当DMA只访问一个内存参数时,可设置成:DMA_MemoryInc_Disable。

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

上面的这句是设置DMA在访问时每次操作的数据长度。有三种数据长度类型,前面已经讲过了,这里不在叙述。

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

与上面雷同。在此不再说明。

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

上面的这句是设置DMA的传输模式:连续不断的循环模式,若只想访问一次后就不要访问了(或按指令操作来反问,也就是想要它访问的时候就访问,不要它访问的时候就停止),可以设置成通用模式:DMA_Mode_Normal

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

上面的这句是设置DMA的优先级别:可以分为4级:VeryHigh,High,Medium,Low.

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

上面的这句是设置DMA的2个memory中的变量互相访问的

DMA_Init(DMA_Channel1,&DMA_InitStructure);

前面那些都是对DMA结构体成员的设置,在次再统一对DMA整个模块做一次初始化,使得DMA各成员与上面的参数一致。

/*DMA Enable*/

DMA_Cmd(DMA_Channel1,ENABLE);

哈哈哈!这一句我想我就不罗嗦了,大家一看就明白。

至此,整个DMA总算设置好了,但是,DMA通道又是怎样与外设联系在一起的呢?哈哈,这也是我当初最想知道的一个事情,别急!容我想喝口茶~~~~~~哈哈哈!

要使DMA与外设建立有效连接,这不是DMA自身的事情,是各个外设的事情,每个外设都有 一个xxx_DMACmd(XXXx,Enable )函数,如果使DMA与ADC建立有效联系,就使用ADC_DMACmd(ADC1,Enable); (这里我启用了ADC中的ADC1模块)。

一个简单的例子 transfer  a word data buffer from FLASH memory to embedded SRAM memory.在V3.1.2库的位置STM32F10x_StdPeriph_Lib_V3.1.2\Project\STM32F10x_StdPeriph_Examples\DMA\FLASH_RAM/* DMA1 channel6 configuration */DMA_DeInit(DMA1_Channel6);//peripheral base addressDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer;//memory base addressDMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DST_Buffer;//数据传输方向    Peripheral is sourceDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//缓冲区大小 Number of data to be transferred (0 up to 65535).数据传输数目DMA_InitStructure.DMA_BufferSize = BufferSize;// the Peripheral address register is incrementedDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;//the memory address register is incrementedDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//the Peripheral data widthDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;//the DMAy Channelx will be used in memory-to-memory transfer

//DMA通道的操作可以在没有外设请求的情况下进行,这种操作就是存储器到存储器模式。DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;

DMA_Init(DMA1_Channel6, &DMA_InitStructure);/* Enable DMA1 Channel6 Transfer Complete interrupt */DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);/* Enable DMA1 Channel6 transfer */DMA_Cmd(DMA1_Channel6, ENABLE);

=======================================================================

外设的DMA请求映像要使DMA与外设建立有效连接,这不是DMA自身的事情,是各个外设的事情,每个外设都有 一个

xxx_DMACmd(XXXx,Enable )函数,如果使DMA与ADC建立有效联系,就使用 ADC_DMACmd

(ADC1,Enable); (这里我启用了ADC中的ADC1模块)。

/* DMA1 channel1 configuration ----------------------------------------------*/

DMA_DeInit(DMA1_Channel1);

DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&AD_Value;

//u16  AD_Value[2];   不加&应该也可以  数组名 代表地址

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = 2;      //############## 改了

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //##############     改了

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel1, &DMA_InitStructure);

/* Enable DMA1 channel 1 */

DMA_Cmd(DMA1_Channel1, ENABLE);

/* ADC1 configuration------------------------------------------------------*/

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

ADC_InitStructure.ADC_ScanConvMode = ENABLE;

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

ADC_InitStructure.ADC_NbrOfChannel = 2;      //##############     改了

ADC_Init(ADC1, &ADC_InitStructure);

//内部温度传感器  添加这一句

/* Enable the temperature sensor and vref internal channel */

ADC_TempSensorVrefintCmd(ENABLE);

//##############     改了

//################ Channel 10(电位器)

ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_13Cycles5);

//###### 内部温度传感器  Channel 16 ###################

ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_55Cycles5);

/* Enable ADC1 DMA */使能ADC1的DMA请求映像

ADC_DMACmd(ADC1, ENABLE);

/* Enable ADC1 */

ADC_Cmd(ADC1, ENABLE);

/* Enable ADC1 reset calibaration register */   //使用之前一定要校准

ADC_ResetCalibration(ADC1);

/* Check the end of ADC1 reset calibration register */

while(ADC_GetResetCalibrationStatus(ADC1));

/* Start ADC1 calibaration */

ADC_StartCalibration(ADC1);

/* Check the end of ADC1 calibration */

while(ADC_GetCalibrationStatus(ADC1));

/* Start ADC1 Software Conversion */

ADC_SoftwareStartConvCmd(ADC1, ENABLE);

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

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

相关文章

管理计算机域内置账户改为用户账户,“管理计算机(域)的内置帐户”我给它改了名...

在Windows XP中,Administrator帐户是终极管理员,如果你创建了其他管理员帐户,那么该帐户就会从欢迎屏幕上被隐藏。这里需要注意的是,仅仅是从欢迎屏幕上被隐藏,该帐户仍然存在。如果你仍然需要使用这个帐户&#xff0c…

程序架构--BS,CS

程序架构 C/S(client/server) QQ 微信 LOL 优点:有一部分代码写在客户端,用户体验比较好 缺点:服务器更新,客户端也随着更新,占用资源大 B/S(browser/server) 网页游戏:WebQQ ... 优点:客…

被称为“第五代 AI”的神经形态计算进展到哪一步了?

来源:北京物联网智能技术应用协会AI可以像人脑一样运作吗?几十年来,研究人员一直在问这个问题,这个大家长期求索的问题引起了质疑、嘲笑、轻蔑等不同态度。但是现在,神经形态计算让世界变得更美好的梦想更近了一些。当…

AngularJS学习笔记(一)

一.基本指令 1、ng-app" " 指令初始化一个 AngularJS 应用程序,定义angularJS的使用范围;tips:一个页面里创建多个 ng-app 手动加载即可:var app1 angular.module("app1", []); var app2 angular.module("app2", []); angular.bootstrap(docum…

oc 画一个圆弧_UG建模一个蜗杆的方法,纯手工建模无插件

上次我们画了一个蜗杆,今天就来建模一个涡轮模型,也是非常简单。这次还是无尺寸的随意建模,做出这么一个涡轮,来看看建模方法吧!1 首先在XY平面上绘制一个直径100的圆,上下拉伸10mm2 对圆柱上下面倒斜角3mm…

计算机基本网络测试命令实验报告,网络连通性测试与网络命令验证实验报告

网络连通性测试与网络命令验证实验报告西工大计算机网络原理实验报告网络原理实验报告实验名称: 网络连通性测试与网络命令验证 日期: 2015.11.09 班级:学号: 姓名:【一】 预习内容5个常用网络命令&#xf…

Leetcode--11. 盛水最多的容器

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多…

《城市大脑全球标准研究报告》发布会将于12月23号在北京举办

城市大脑全球标准研究组《城市大脑全球标准研究报告》发布会将于2020年12月23日下午在北京海淀区城市大脑展览厅举办,发布会除了报告发布,智能产业专家演讲,也将参观海淀城市大脑的发展情况。欢迎新闻媒体、科研机构、科技企业、政府部门的记…

竞态条件与临界区

在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源。如,同一内存区(变量,数组,或对象)、系统(数据库,web services等)或文件。实际上&#xf…

java 实现打印条形码_条码打印软件中如何设置条形码下面的字符间距?

条形码有两部分组成,上面是黑白条图案,用于扫描设备的识别,下面是条形码数据,方便在没有扫描设备的情况下可以手动去搜索相关的信息。一般用条码打印软件制作条形码,下面的条形码数据间距是自动生成的,而在…

计算机科学分为几个部分,计算机由几部分组成各部分的功能是什么

推荐回答一、数值计算计算机广泛地应用于科学和工程技术方面的计算,这是计算机应用的一个基本方面,也是我们比较熟悉的。如:人造卫星轨迹计算,导弹发射的各项参数的计算,房屋抗震强度的计算等。二、数据处理用计算机对…

用跑得最慢的电脑程序,理解最高深的哥德巴赫猜想

五条规则的图灵机可视化。每列像素代表一步计算,步骤从左到右。黑色代表1。最右边表示图灵机的停机。(图片来源:Peter Krumins/Quanta Magazine)文章来源:环球科学“忙碌的河狸”这个问题的目的是为了找到运行时间最长…

Leetcode--42.接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水&#…

(4)Python3笔记 之 流程控制

一、条件控制 # 语法规则 if 变量(或表达式):语句块1 elif 变量(或表达式):语句块2 else:语句块3#示例 score 83 if score > 90:print(优秀) elif score > 60 and score < 90:print(及格) else:print(不及格) 二、循环 1&#xff09;. while循环 i 0 sum 0 while i…

云专网和云专线的区别_传统IDC行业与云计算的区别?

1.传统IDC行业和云计算在服务类型上的区别&#xff1a;传统IDC行业主要是有两种模式&#xff1a;租用和托管租用是自己没有服务器&#xff0c;机房提供服务器、带宽、IP地址、机位、服务器维护等。这种模式是租用。托管是自己购买配置服务器&#xff0c;通过快递、物流等方式把…

计算机插件技术应用原理,计算机软件技术中插件技术的运用

计算机软件技术中插件技术的运用在我国科技水平的不断提升下,计算机软件方面的功能也在持续更新。其中插件技术作为计算机软件中实用性比较强的一项功能,一直被研究分析。下面是小编搜集整理的相关内容的论文&#xff0c;欢迎大家阅读参考。摘要&#xff1a;随着经济和科学技术…

未来30年,这20项技术将颠覆人类生活

来源&#xff1a;嵌入式资讯精选美国公布了一份长达35页的《新兴科技趋势报告》。该报告是在美国过去五年内由政府机构、咨询机构、智囊团、科研机构等发表的32份科技趋势相关研究调查报告的基础上提炼形成的。通过对近700项科技趋势的综合比对分析&#xff0c;最终明确了20项最…

攻克数据库核心技术壁垒,实现百万级QPS的高吞吐

CynosDB是腾讯云自研的新一代高性能高可用的企业级分布式云数据库。融合了传统数据库、云计算与新硬件的优势&#xff0c;100%兼容开源数据库&#xff0c;百万级QPS的高吞吐&#xff0c;不限存储&#xff0c;价格仅为商用数据库的1/10。 CynosDB设计出发点: 随着云计算2.0时代的…

Leetcode--55. 跳跃游戏

给定一个非负整数数组&#xff0c;你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个位置。 示例 1: 输入: [2,3,1,1,4] 输出: true 解释: 从位置 0 到 1 跳 1 步, 然后跳 3 步到达最后一个位置。 示例 2: 输…

ccxprocess启动项可以禁用么_Mac怎么禁用Adobe无用自启项?

最近有使用Mac的用户询问小编Mac如何禁用Adobe无用自启项&#xff1f;每次开机Adobe都会无用自启&#xff0c;那么Mac如何禁用Adobe无用自启项&#xff0c;跟着小编一起来看看Mac禁用Adobe无用自启项教程。Mac禁用Adobe无用自启项教程&#xff1a;一&#xff1a;通过以下路径找…