stm32 DMA
目录
简介
框图
DMA请求
DMA通道
DMA优先级
DMA 数据
外设到存储器
存储器到外设
存储器到存储器
传多少,单位是什么
传输完成
hal库代码
标准库代码
简介
CPU根据代码内容执行指令,这些众多指令中,有的用于计算、有的用于控制程序、有的用于转移数据等。 其中转移数据的指令,尤其是转移大量数据,会占用大量CPU。如果是把外设A的数据,传给外设B,这种情况其实不需要CPU一直参与,只需在A、 B之间创建个通道,让它们自己传输即可。DMA(Direct Memory Access)直接内存访问,可以大大减轻CPU工作量。这就DMA设计的目的,减少大量数据转移指令消耗CPU, DMA专注数据转移, CPU专注计算、控制。
DMA主要实现将A处的数据直接搬运到B处,场景如下三种:内存到外设、外设到内存、内存到内存。无论是何种方式,都是先设置好DMA的数据源地址、数据目标地址、数据长度。设置好后,启动DMA就可以自动的把数据从源地址依次传输到目标地址。
框图
STM32F1系列有两个DMA控制器, 其中DMA2仅存在于大容量产品中。 DMA1有7个通道, DMA2有5个通道,总计12个通道。这里的通道可以理解为传输数据的一种管道。

DMA请求

外设想通过DMA传输数据,需要先向DMA控制器发送请求。 外设向DMA控制器发送请求后, DMA控制器根据通道优先级依次处理请求,控制器会给外设一个应答信号,当外设应答后且 DMA 控制器收到应答信号之后,就会启动 DMA 的传输,直到传输完毕
DMA 有 DMA1 和 DMA2 两个控制器, DMA1 有 7 个通道, DMA2 有 5 个通道,不同的 DMA 控制器的通道对应着不同的外设请求
DMA通道


不同的外设,向不同DMA的不同通道发送请求。比如ADC1想使用DMA,应向DMA1的通道1发送请求。 DMA1的通道1,可以接收多个外设的请求( ADC1、 TIM2_CH3、TIM4_CH1),但同一时间只能接收一个
DMA优先级

当多个DMA通道,同时发来请求时,这个就由仲裁器管理。仲裁器管理 DMA 通道请求分为两个阶段。第一阶段属于软件阶段,获取软件配置DMA_CCRx寄存器设置的优先级,有 4 个等级:非常高,高,中和低四个优先级依次响应。第二阶段属于硬件阶段,当软件配置优先级相同时,硬件优先级高的(通道编号小的)优先响应。DMA1 控制器拥有高于 DMA2 控制器的优先级。
DMA 数据
外设到存储器
比如ADC 采集配置,DMA 外设寄存器的地址对应的就是 ADC数据寄存器的地址, DMA 存储器的地址就是我们自定义的变量(用来接收存储 AD 采集的数据)的地址。方向设置外设为源地址。
存储器到外设
比如串口向电脑端发送数据,DMA 外设寄存器的地址对应的就是串口数据寄存器的地址, DMA 存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储通过串口发送到电脑的数据)的地址。方向设置外设为目标地址。
存储器到存储器
比如内部 FLASH 向内部 SRAM 复制数据,DMA 外设寄存器的地址对应的就是内部 FLASH(把内部 FALSH 当作外设来看)的地址, DMA存储器的地址就是我们自定义的变量(相当于一个缓冲区,用来存储来自内部 FLASH 的数据)的地址。方向我们设置外设(即内部FLASH)为源地址。跟上面不一样的是,这里需要把DMA_CCR 位 14: MEM2MEM:存储器到存储器模式配置为 1,启动 M2M 模式
传多少,单位是什么
一个 32 位的寄存器,DMA一次可传输的最多65536个数据, 要想数据传输正确,源和目标地址存储的数据宽度还必须一致,如串口数据寄存器是 8 位的,所以要发送的数据也必须是 8 位。
数据要想有条不紊的从一个地方搬到另外一个地方,还必须正确设置两边数据指针的增量模式。以串口向电脑发送数据为例,要发送的数据很多,每发送完一个,那么存储器的地址指针就应该加 1,而串口数据寄存器只有一个,那么外设的地址指针就固定不变。具体的数据指针的增量模式由实际情况决定
传输完成
DMA在传输过程中会产生3个传输标志:半完成标志( Half Transfer, HT) 、完成标志( Transfer Complete, TC) 和错误标志( Transfer Error, TE) 。数据什么时候传输完成,可以通过查询标志位或者通过中断的方式来鉴别
每个标志会产生对应的中断信号,如果使能了三种类型的中断后,则会产生中断。假如有N个数据待DMA传输,设置到原地址和目的地址后,当收到一个传输请求DMA就会从原地址取出一个数据传输到目的地址,如果地址是外设则地址保持不变,若地址是内存则传输完一个数据之后地址自增一个数据单位。在传输过程中如果发生意外错误则会产生一个错误中断信号,当传输完成一半则会产生半传输完成中断,当全部数据都传输完成则会产生一个传输完成中断。
hal库代码
DMA_HandleTypeDef hdma;
/*标志位*/
__IO uint32_t transferErrorDetected;
__IO uint32_t transferCompleteDetected;/*发送缓冲区*/
uint32_t src_buffer[20] ={0x1234, 0x5678, 0x9876, 0x4586, 0xABCD,0x5678, 0xABCD, 0x4586, 0x4586, 0xABCD,0xABCD, 0x5678, 0x4586, 0x9876, 0x1234,0x1234, 0xABCD, 0x9876, 0x5678, 0xABCD,};
/*接收*/
uint32_t dst_buffer[20] = {0};#if 1
/*如果DMA传输完成且不发生错误,则在此函数将传输完成标志置一*/
static void tranfer_complete(DMA_HandleTypeDef *dma)
{transferCompleteDetected=1;
}
/*如果DMA传输过程中发生错误,则在此函数中将传输错误标志置一*/
static void tranfer_error(DMA_HandleTypeDef *dma)
{transferErrorDetected=1;
}
#endifvoid dma_init(void)
{/*使能DMA1时钟*/__HAL_RCC_DMA1_CLK_ENABLE();hdma.Init.Direction = DMA_MEMORY_TO_MEMORY;/*内存到内存模式*/hdma.Init.PeriphInc = DMA_PINC_ENABLE;/*外设地址递增*/hdma.Init.MemInc = DMA_MINC_ENABLE;/*内存地址递增*/hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;/*外设数据以字对齐*/hdma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;/*内存数据以字对齐*/hdma.Init.Mode = DMA_NORMAL;/*正常传输模式,传输一次*/hdma.Init.Priority = DMA_PRIORITY_VERY_HIGH;/*传输优先级非常高*/hdma.Instance = DMA1_Channel1;/*选择DMA通道1*//*初始化配置*/HAL_DMA_Init(&hdma);
#if 1/*注册传输完成和传输错误回调函数*/HAL_DMA_RegisterCallback(&hdma, HAL_DMA_XFER_CPLT_CB_ID,tranfer_complete);/*传输完成的回调函数 ID*/HAL_DMA_RegisterCallback(&hdma, HAL_DMA_XFER_ERROR_CB_ID, tranfer_error);/*DMA中断优先级*/HAL_NVIC_SetPriority(DMA1_Channel1_IRQn , 0 , 0);HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
#endif}#if 1
/*DMA1通道1中断的中断处理函数*/
void DMA1_Channel1_IRQHandler(void)
{HAL_DMA_IRQHandler(&hdma);
}/*初始化 DMA_Channel1,配置为内存-内存模式,每次搬移一个 word 即 4bytes*/
void dma_start(uint32_t *SrcAddress, uint32_t *DstAddress, uint16_t DataLength)
{HAL_DMA_Start_IT(&hdma,(uint32_t)SrcAddress,(uint32_t)DstAddress,DataLength);
}
#endif
标准库代码
/*时钟使能的dma*/
#define CLK_DMAx RCC_AHBPeriph_DMA1
/*串口对应的DMA请求通道*/
#define USART_TX_DMA_CHANNEL DMA1_Channel4
/*外设接收数据寄存器地址*/
#define USART_DR_ADDRESS (USART1_BASE+0x04)
/*一次发送的数据量 <65535*/
#define SIZE 5000static uint32_t i;
uint8_t send_buf[SIZE];void uart_dma_init(void)
{DMA_InitTypeDef DMA_InitStruct;/*开启时钟*/RCC_AHBPeriphClockCmd(CLK_DMAx,ENABLE);/*设置DMA源地址:串口数据寄存器地址*/DMA_InitStruct.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;/*内存地址,使DMA传输的数据从`send_buf`所指向的内存开始*/DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)send_buf;/*方向:内存到外设*/DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;/*传输大小*/DMA_InitStruct.DMA_BufferSize = SIZE;/*外设地址不增*/DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;/*内存地址只增*/DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;/*外设数据单位*/DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;/*内存数据单位,每次传输的数据大小为1字节*/DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;/*dma模式,一次或循环*/DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;/*一次*///DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;/*循环*//*优先级:中*/DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;/*内存到内存的传输*/DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;/*配置DMA通道*/DMA_Init(USART_TX_DMA_CHANNEL,&DMA_InitStruct);/*使能DMA*/DMA_Cmd(USART_TX_DMA_CHANNEL,ENABLE);/*使能USART的DMA传输功能,具体传输方向为USART的发送(Tx)方向。*///USART_DMACmd(USARTx,USART_DMAReq_Tx,ENABLE);
}/*发送*/
void dma_send(void)
{/*填充要发送的数据*/for(i=0;i<SIZE;i++){send_buf[i] = 'p';}
/*开启传输,USARTx表示要配置的USART接口,USART_DMAReq_Tx表示启用发送数据的DMA请求*/USART_DMACmd(USARTx,USART_DMAReq_Tx,ENABLE);}
相关文章:
stm32 DMA
目录 简介 框图 DMA请求 DMA通道 DMA优先级 DMA 数据 外设到存储器 存储器到外设 存储器到存储器 传多少,单位是什么 传输完成 hal库代码 标准库代码 简介 CPU根据代码内容执行指令,这些众多指令中,有的用于计算、有的用于控制程…...
厦门万宾科技智能井盖监测仪器的作用如何?
越来越多的人们希望改善生活,走出农村走出大山,前往城市之中居住。由此城市的人口和车辆在不断增加,与之而来的是城市的交通压力越来越大,时常会出现道路安全隐患,这给城市未来发展和智慧城市建设都带来一定的难题&…...
【带头学C++】----- 三、指针章 ---- 3.5 字符串与指针
在 C 中,字符串可以通过指针来表示和操作。C 的字符串是由字符组成的字符数组,而指针则用于引用和操作内存中的数据。 1. 字符数组 1. 字符数组: 字符数组是最基本的字符串表示方式。可以使用字符数组来存储字符串,并使用指针来引用它。字符…...
二十三种设计模式全面解析-深入解析桥接模式:解锁软件设计的灵活性
在软件开发中,我们经常面临需要处理多个不同维度变化的情况。这些变化可能涉及多个维度的组合,导致类的爆炸性增长和难以维护的代码。在这种情况下,桥接模式(Bridge Pattern)是一种强大的设计模式,能够帮助…...
Ansible中的角色使用
Ansible中的角色使用: 目录 一、ansible角色简介 二、roles目录结构 三、roles的创建 四、roles的使用 1、书写task主任务 2、触发器模块 3、变量模块 4、j2模块 5、files模块 6、启用模块 7、执行playbook 五、控制任务执行顺序 六、多重角色的使用 一…...
C通过指针访问数组元素
在C语言中,数组除了通过数组索引访问,也可以通过指针来访问数组中的元素。下面是一个简单的例子: #include <stdio.h>int main() {int array[5] {1, 2, 3, 4, 5};int *ptr array; // 指向数组的第一个元素的指针printf("数组元…...
程序员成长树
- 10年以后我在做什么? 成为项目负责人(管理事、管理人) - 如何处理同事的关系: 平时生活中最简单的一句问候,闲暇时间的聊天了解,互帮互助 - miss yang: - 1、软件UI设计 - 2、需求分析 - 3、协调推进任务的安排 …...
数字化时代,数据仓库是什么?有什么用?
在激烈的市场竞争和全新的数字经济共同作用下,数字化转型成为了大多数企业的共识,也是获取数字经济的最佳方式。在整个数据价值生产链路中,数据仓库的主要作用就是中心化分发,将原始数据与数据价值挖掘活动隔离。 所有的原始数据…...
android NetworkMonitor和ConnectivityService记录
一、NetworkMonitor packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java 网络上都叫网络可用性校验,在WIFI和数据(以太网切换中使用) 有多个状态机 方法:isCaptivePortal 11-03 12:01:17…...
Technology strategy Pattern 学习笔记1-Context: Architecture and Strategy
Context: Architecture and Strategy 1 Architect and Strategist 1.1 three primary concerns of the architect 1.1.1 Contain entropy(熵-混乱程度,不确定性,惊奇程度,不可预测性,信息量等等) The architect wh…...
数据结构-顺序表
1.线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的一条直线…...
数据结构与算法 | 第三章:栈与队列
本文参考网课为 数据结构与算法 1 第三章栈,主讲人 张铭 、王腾蛟 、赵海燕 、宋国杰 、邹磊 、黄群。 本文使用IDE为 Clion,开发环境 C14。 更新:2023 / 11 / 5 数据结构与算法 | 第三章:栈与队列 栈概念示例 实现顺序栈类定义…...
oracle查询数据库内全部的表名、列明、注释、数据类型、长度、精度等
Oracle查询数据库内全部的表名、列明、注释、数据类型、长度、精度 SELECT a.TABLE_NAME 表名, row_number() over(partition by a.TABLE_NAME order by a.COLUMN_NAME desc) 字段顺序,a.COLUMN_NAME 列名, b.COMMENTS 注释,a.DATA_TYPE 数据类型, a.DATA_LENGTH 长度,DATA_SC…...
数据可视化:折线图
1.初看效果 (1)效果一 (2)数据来源 2.JSON数据格式 其实JSON数据在JAVA后期的学习过程中我已经是很了解了,基本上后端服务器和前端交互数据大多是采用JSON字符串的形式 (1)JSON的作用 &#…...
Python语言_matplotlib包_共80种--全平台可用
Python语言_matplotlib包_共80种–全平台可用 往期推荐: Python语言_single_color_共140种–全平台可用 R语言_RColorBrewer包–全平台可用 R语言gplots包的颜色索引表–全平台可用 R语言中的自带的调色板–五种–全平台可用 R语言657中单色colors颜色索引表—全平台…...
OpenFeign 的超时重试机制以及底层实现原理
目录 1. 什么是 OpenFeign? 2. OpenFeign 的功能升级 3. OpenFeign 内置的超时重试机制 3.1 配置超时重试 3.2 覆盖 Retryer 对象 4. 自定义超时重试机制 4.1 为什么需要自定义超时重试机制 4.2 如何自定义超时重试机制 5. OpenFeign 超时重试的底层原理 5…...
redis安装
redis安装 mac下直接安装 mac下安装redis还是很简单的(其实mac下安装什么软件都挺简单的,brew啥都有) brew install redis 之后就是漫长的等待,下了好久,终于下载完了 修改redis.conf中的配置 # 后台启动daemonize yes 启动服务端 redis-serv…...
VM虚拟机逆向 --- [NCTF 2018]wcyvm 复现
文章目录 前言题目分析 前言 第四题了,搞定,算是独立完成比较多的一题,虽然在还原汇编的时候还是很多问题。 题目分析 代码很简单,就是指令很多。 opcode在unk_6021C0处,解密的数据在dword_6020A0处 opcode [0x08, …...
2024天津理工大学中环信息学院专升本机械设计制造自动化专业考纲
2024年天津理工大学中环信息学院高职升本科《机械设计制造及其自动化》专业课考试大纲《机械设计》《机械制图》 《机械设计》考试大纲 教 材:《机械设计》(第十版),高等教育出版社,濮良贵、陈国定、吴立言主编&#…...
华为OD机试 - 服务失效判断 - 逻辑分析(Java 2023 B卷 200分)
目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出3、说明 四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题&a…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
