当前位置: 首页 > news >正文

STM32 DMA入门指导

什么是DMA

DMA,全称直接存储器访问(Direct Memory Access),是一种允许硬件子系统直接读写系统内存的技术,无需中央处理单元(CPU)的介入。下面是DMA的工作原理概述:
数据传输触发:DMA传输可以由CPU指令触发,也可以由硬件事件(如一个外设准备好数据)自动触发。
外设和内存之间的数据交换:一旦DMA传输开始,DMA控制器会将数据从源地址直接传送到目的地址。源地址常常是外设的数据寄存器,目的地址通常是内存中的一个缓冲区;反之亦然。
CPU解放:在没有DMA的情况下,CPU需要执行多个指令来完成数据的传送,包括数据的读取和写入操作。当使用DMA时,CPU只需初始化传输,之后DMA控制器将自动处理数据传送,CPU则可以执行其他任务。
传输完成中断:当所有数据都被传输至目的地之后,DMA控制器会向CPU发送一个中断信号。这个中断告知CPU数据已经成功传输完毕,CPU随后可以进行后续处理,比如停止DMA,处理数据,或重新初始化另一次DMA传输。
优先级和通道:DMA控制器可能有多个通道,每个通道可以独立配置并与特定的外设关联。在多通道DMA系统中,可能会有优先级设置,以决定哪个DMA请求被优先处理。
DMA是提高数据传输效率、减少CPU负荷、优化系统性能的有效手段,特别是在处理高速数据流或频繁数据传输时。在嵌入式系统和计算机架构中,有了DMA,CPU就可以更有效地处理逻辑计算和数据处理任务,而不是花费大量时间在数据移动上。

DMA可以用于哪些数据传输方式?

DMA 可以用于多种数据传输方式,包括:
1、内存到内存:数据可以直接从一个内存地址复制到另一个内存地址,无需CPU的介入。
2、外设到内存:数据从外设(如ADC,UART接收缓冲区,SPI等)直接传输到内存。这通常用于从外设读取数据时。
3、内存到外设:数据从内存直接传输到外设(如DAC,UART发送缓冲区,SPI等)。这通常在向外设写入数据时使用。
4、外设到外设:虽然不是所有DMA控制器都支持这个功能,但有些高级系统允许直接从一个外设到另一个外设的数据传输,不经过内存。
这些传输方式中,最常见的使用场景是外设到内存和内存到外设。因为这可以大幅度减轻CPU的工作负担,尤其是在数据流量较大时,如从网络接口接收数据包,或向图形处理器发送图像数据。 

DMA初始化的步骤有哪些?

DMA初始化的步骤通常如下所示:
1、DMA控制器时钟使能:
通过 RCC(Reset and Clock Control)模块使能 DMA 控制器的时钟。
2、DMA通道配置:
        a、为目标 DMA 通道配置传输方向(从内存到外设、从外设到内存或者内存到内存)。
        b、设置源地址和目的地址及其增量模式(地址在传输后是否递增)。
        c、配置数据大小(传输的数据宽度,一般为8位、16位或32位)。
        d、设定传输数据的数量(数据块大小)。
3、外设配置:
如果外设(如 ADC, UART, SPI)使用 DMA 进行数据传输,需要在外设的配置中使能相应的 DMA 传输请求。
4、中断配置(可选):
根据实际需要,可以配置并使能传输完成、半传输完成及传输错误中断。
5、DMA流控制(如果适用):
在某些情况下,特别是在使用双缓冲或循环模式时,可能需要配置 DMA 流控制。
6、启动DMA传输:
使用相应的库函数或直接通过控制寄存器启动 DMA 传输。

重要寄存器

STM32微控制器中的DMA(直接存储器访问)寄存器包括几组关键的控制和状态寄存器,用于管理和监控DMA的操作。具体的寄存器会根据STM32的不同系列及其内部架构的差异而有所不同,但一般而言,一个DMA通道会涉及以下几个主要寄存器:
1、DMA控制寄存器 (DMA_CCRx):
控制传输的基本配置,包括传输方向、传输模式(正常或循环模式)、优先级、内存和外设大小、内存增量模式、外设增量模式等。
2、DMA数量寄存器 (DMA_CNDTRx):
包含被传输数据的数量。一次DMA操作开始前,此寄存器需要被加载。
3、DMA外设地址寄存器 (DMA_CPARx):
保存外部外设的基地址。
4、DMA内存地址寄存器 (DMA_CMARx):
保存内存的基地址。这是数据要被传输到或从中传输出的内存位置。
5、DMA状态寄存器 (DMA_ISR):
表示每个通道的状态,包括传输完成、半传输、传输错误和全局中断标志。
6、DMA标志清除寄存器 (DMA_IFCR):
用于清除特定通道的中断标志位。

DMA的状态寄存器具体表示了哪些通道的状态?

DMA的状态寄存器提供了关于各通道传输状态的具体信息,主要包括:
1、传输完成(TC):指示相应DMA通道是否已经完成所配置的数据传输任务。
2、半传输(HT):指示相应DMA通道是否已经完成一半的数据传输(对于某些应用可能需要在传输一半时进行处理)。
3、传输错误(TE):如果DMA通道在传输过程中遇到错误,该标志会被置位。
这些状态可以用来触发中断服务程序(Interrupt Service Routines, ISRs), 允许软件响应DMA传输的完成或错误。开发者通常会在对应的中断处理函数中检查这些状态,以确定传输是否成功,或者是否需要采取措施来处理错误情况。

 
DMA的中断服务程序是如何触发的?

DMA的中断服务程序(ISR)是通过设置DMA控制寄存器中的中断使能位来触发的。具体触发步骤如下:
1、使能中断:在初始化DMA时,你需要在DMA通道的控制寄存器(DMA_CCRx)中使能传输完成中断、半完成中断和/或传输错误中断。
2、配置NVIC:在嵌套向量中断控制器(NVIC)中,你需要为对应的DMA通道中断配置优先级,并使能中断。
3、中断发生:
        a、当DMA传输完指定数量的数据后,如果启用了传输完成中断,DMA控制器将设置状态寄存器(DMA_ISR)的传输完成标志(TC)。
       b、 如果启用了半传输中断,当传输完成一半的数据量时,DMA控制器将设置状态寄存器的半传输完成标志(HT)。
        c、如果在传输过程中发生任何错误,如FIFO溢出或者总线错误等,DMA控制器将设置状态寄存器的传输错误标志(TE)。
4、中断处理:一旦相应的标志位被置位,如果NVIC中对应的中断已使能,CPU将暂停当前任务,跳转到对应的中断服务程序执行中断处理代码。
5、中断标志清除:在中断服务程序中,需要手动清除DMA的状态寄存器中的中断标志位,以防止重复进入中断服务程序。
通过以上步骤,STM32 中的DMA中断服务程序可以在特定的事件发生时被触发,以便进行如数据处理、错误处理等操作。

代码演示

下面是一个简单的STM32程序例子,用于演示如何使用DMA将数据从一个数组复制到另一个数组(内存到内存的DMA传输)

#include "stm32f4xx.h"
// 定义数组大小
#define ARRAYSIZE 5
// 定义源数组和目标数组
uint32_t srcArray[ARRAY_SIZE] = {1, 2, 3, 4, 5};
uint32_t destArray[ARRAY_SIZE] = {0, 0, 0, 0, 0};
void DMA_Config(void)
{// 手动使能DMA1时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);// 创建DMA初始化结构体并填入配置DMA_InitTypeDef DMA_InitStructure;DMA_DeInit(DMA1_Stream0);  // 将DMA Stream恢复到初始状态DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&srcArray;  // 设置DMA源地址DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&destArray;    // 设置DMA目标地址DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;  // 设置内存到内存模式DMA_InitStructure.DMA_BufferSize = ARRAY_SIZE;  // 传输的数据大小DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;   // 外设地址递增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;   // 内存地址递增DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; // 32位数据宽度DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; // 32位数据宽度DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;   // 设置为正常模式DMA_InitStructure.DMA_Priority = DMA_Priority_Low; // 设置优先级为低DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;  // FIFO模式禁用DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; // FIFO阈值设置DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; // 单次突发模式DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 单次突发模式// 初始化DMADMA_Init(DMA1_Stream0, &DMA_InitStructure);// 使能DMA流DMA_Cmd(DMA1_Stream0, ENABLE);// 如果都是定期的规律的检查传输状态,可以留空这里// 如果你需要传输完成的通知,可能需要使用中断和相应的服务函数
}
int main(void)
{// 系统初始化SystemInit();// 配置DMADMA_Config();// 在这里,我们假定系统只是简单地执行一次内存到内存的复制// 复制完后,可以添加代码检查destArray数组中的值// 这里以简单的检查第一个元素是否等于1为例if (destArray[0] == 1){// 如果传输成功,将会进入到这里}// 主循环,程序可以继续执行或者进入睡眠while (1){}
} 

相关文章:

STM32 DMA入门指导

什么是DMA DMA,全称直接存储器访问(Direct Memory Access),是一种允许硬件子系统直接读写系统内存的技术,无需中央处理单元(CPU)的介入。下面是DMA的工作原理概述: 数据传输触发&am…...

mysql根据指定顺序返回数据--order by field

在查询数据的时候,在in查询的时候,想返回的数据根据 in里的数据顺序返回,可以直接在orderby中通过 FIELD(字段名称逗号分隔的值的顺序) 进行指定;示例没有加 order by field添加 order by field效果...

IEEE SGL与NVMe SGL的区别?

在HBA(Host Bus Adapter)驱动程序中,IEEE SGL(Institute of Electrical and Electronics Engineers Scatter-Gather List)和NVMe SGL(Non-Volatile Memory Express Scatter-Gather List)是两种不…...

struct内存对齐

5.1.3 struct内存对齐 结构体的对齐规则: (1)第一个成员在与结构体偏移量为0的地址处。 (2)其他成员变量要对齐到对齐数的整数倍的地址处 对齐数 编译器默认的对齐数与该成员大小的较小值。(vs中默认值为8) (3)结构体总大小为最大对齐数…...

探索Redis 6.0的新特性

Redis(Remote Dictionary Server)是一个开源的内存中数据结构存储系统,通常被用作缓存、消息队列和实时数据处理等场景。它的简单性、高性能以及丰富的数据结构支持使其成为了众多开发者和企业的首选。在Redis 6.0版本中,引入了一…...

关于CSS中定位的教程

在CSS中,定位是一种强大的工具,可以帮助我们控制元素在页面上的位置。通过使用定位属性,我们可以精确地放置元素在页面的任何位置,并且可以实现各种复杂的布局效果。在本教程中,我们将深入探讨CSS中的定位属性&#xf…...

抽象类、模板方法模式

抽象类概述 在Java中abstract是抽象的意思,如果一个类中的某个方法的具体实现不能确定,就可以申明成abstract修饰的抽象方法(不能写方法体了),这个类必须用abstract修饰,被称为抽象类。 抽象方法定义&…...

消息队列kafka

消息队列解决的问题 1. 解耦,通过消息队列实现应用之间解耦,模块儿之间解耦 2. 跨线程/进程通信,通过消息队列传递数据,实现不同线程/进程间通信 3. 提升系统稳定性,在高并发场景通过消息队列缓冲,可以实…...

复盘成长——2024.2月复盘

复盘的目的和范围 每月一次的精心复盘,不仅是对自身工作成就、学习进步与成长轨迹的深度梳理,更是一种对未来路径的细致规划。通过这一过程,我期望能够更加精准地把握生活的节奏和职场的航向,从中汲取经验、聚焦目标,…...

Kafka安全模式之身份认证

一、简介 Kafka作为一个分布式的发布-订阅消息系统,在日常项目中被频繁使用,通常情况下无论是生产者还是消费者只要订阅Topic后,即可进行消息的发送和接收。而kafka在0.9.0.0版本后添加了身份认证和权限控制两种安全服务,本文主要…...

3、Redis-List【常用】

目录 一、重要特点 二、常用命令 三、Redis中List类型应用场景 一、重要特点 ①Redis中的List,视为双向链表 ②Redis中的List,数据可以重复 二、常用命令 常用命令 格式含义例子rpush key value从右边往key中添加value值rpush hobby java pythonlpu…...

黑马c++ STL部分 笔记(7) list容器

list基本概念 功能:将数据进行链式存储 链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的 链表的组成:链表由一系列结点组成结点的组成:一个是存储数据元素…...

关于使用Mxnet GPU版本运行DeepAR报错解决方案

1.引言 我们经常使用GPU来训练和部署神经网络,因为与CPU相比,它提供了更多的计算能力。在本教程中,我们将介绍如何将GPU与MXNet GluonTS一起使用。 首先,确保您的机器中至少有一个Nvidia GPU,并正确安装了CUDA以及CUDN…...

【STM32】江科大STM32学习笔记汇总(50)

00. 目录 文章目录 00. 目录01. STM32学习笔记汇总02. 相关资料下载03. 附录 01. STM32学习笔记汇总 【STM32】STM32学习笔记-课程简介(01) 【STM32】STM32学习笔记-STM32简介(02) 【STM32】STM32学习笔记-软件安装(03) 【STM32】STM32学习笔记-新建工程(04) 【STM32】STM…...

LabVIEW非接触式电阻抗层析成像系统

LabVIEW非接触式电阻抗层析成像系统 非接触式电阻抗层析成像(NEIT)技术以其无辐射、非接触、响应速度快的特点,为实时监测提供了新的解决方案。基于LabVIEW的电阻抗层析成像系统,实现了数据的在线采集及实时成像,提高…...

蓝桥杯备战刷题three(自用)

1.合法日期 #include <iostream> #include <map> #include <string> using namespace std; int main() {map<string,int>mp;int days[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};for(int i1;i<12;i){for(int j1;j<days[i];j){string sto_strin…...

密码学——二次剩余

引言 二次剩余在许多密码学算法和数论问题中具有重要的作用,这个概念涉及到同余方程等概念。 同余 学习二次剩余的概念,首先要了解同余方程的概念,首先默认研究范围为整数,假设 f ( x ) f(x) f(x)是一个整系数多项式,我们讨论是否有整数值x满足同余式 f (...

10.7、华为数通HCIP-DataCom H12-821单选题:121-140

121、关于OSPF特性描述错误的是:D A、OSPF采用链路状态算法。 B、每个路由器通过泛洪 LSA 向外发布本地链路状态信息 C、每台 OSPF 设备都会收集其它路由器发来的LSA 所有的LSA 放在一起便组成了链路状态数据库LSDB, D、OSPF 区域0中所有路由器的 LSDB 都相同。 E、每台…...

多租户篇 | MatrixOne与MySQL全面对比

MySQL 是经典的关系型数据库管理系统&#xff0c;以其简单易用的特性在中小型业务系统中广受开发人员的喜爱。但是MySQL的架构也具有一定的局限性&#xff0c;在需要具备"隔离性"的业务&#xff0c;例如 SaaS 系统或微服务架构等对"数据隔离"及"资源隔…...

python Matplotlib Tkinter-->导出pdf报表

环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 reportlab 4.0.9 import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import tkinter as tk import tkinter.messagebox as messagebox impor…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

SQL注入篇-sqlmap的配置和使用

在之前的皮卡丘靶场第五期SQL注入的内容中我们谈到了sqlmap&#xff0c;但是由于很多朋友看不了解命令行格式&#xff0c;所以是纯手动获取数据库信息的 接下来我们就用sqlmap来进行皮卡丘靶场的sql注入学习&#xff0c;链接&#xff1a;https://wwhc.lanzoue.com/ifJY32ybh6vc…...

(12)-Fiddler抓包-Fiddler设置IOS手机抓包

1.简介 Fiddler不但能截获各种浏览器发出的 HTTP 请求&#xff0c;也可以截获各种智能手机发出的HTTP/ HTTPS 请求。 Fiddler 能捕获Android 和 Windows Phone 等设备发出的 HTTP/HTTPS 请求。同理也可以截获iOS设备发出的请求&#xff0c;比如 iPhone、iPad 和 MacBook 等苹…...

软件工程教学评价

王海林老师您好。 您的《软件工程》课程成功地将宏观的理论与具体的实践相结合。上半学期的理论教学中&#xff0c;您通过丰富的实例&#xff0c;将“高内聚低耦合”、SOLID原则等抽象概念解释得十分透彻&#xff0c;让这些理论不再是停留在纸面的名词&#xff0c;而是可以指导…...