(STM32笔记)十二、DMA的基础知识与用法 第三部分
我用的是正点的
STM32F103
来进行学习,板子和教程是野火的指南者
。
之后的这个系列笔记开头未标明的话,用的也是这个板子和教程。
DMA的基础知识与用法
- 三、DMA程序验证
- 1、DMA 存储器到存储器模式实验
- (1)DMA结构体解释
- (2)DMA结构体初始化
- (3)程序验证
- 2、DMA 存储器到外设模式实验
- (1)串口初始化
- (2)DMA结构体初始化
- (3)程序验证
三、DMA程序验证
1、DMA 存储器到存储器模式实验
(1)DMA结构体解释
typedef struct
{uint32_t DMA_PeripheralBaseAddr; // 外设地址uint32_t DMA_MemoryBaseAddr; // 存储器地址uint32_t DMA_DIR; // 传输方向uint32_t DMA_BufferSize; // 传输数目uint32_t DMA_PeripheralInc; // 外设地址增量模式uint32_t DMA_MemoryInc; // 存储器地址增量模式uint32_t DMA_PeripheralDataSize; // 外设数据宽度uint32_t DMA_MemoryDataSize; // 存储器数据宽度uint32_t DMA_Mode; // 模式选择uint32_t DMA_Priority; // 通道优先级uint32_t DMA_M2M; // 存储器到存储器模式
} DMA_InitTypeDef;
-
DMA_PeripheralBaseAddr
:
外设地址,设定DMA_CPAR
寄存器的值;一般设置为外设的数据寄存器地址,如果是存储器到存储器模式则设置为其中一个存储器地址。 -
DMA_Memory0BaseAddr
:
存储器地址,设定DMA_CMAR
寄存器值;一般设置为我们自定义存储区的首地址。 -
DMA_DIR
:
传输方向选择,可选外设到存储器、存储器到外设。它设定DMA_CCR
寄存器的DIR[1:0]
位的值。这里并没有存储器到存储器的方向选择,当使用存储器到存储器时,只需要把其中一个存储器当作外设使用即可。
-
DMA_BufferSize
:
设定待传输数据数目,初始化设定DMA_CNDTR
寄存器的值。
这个DMA_BufferSize
就是要传输的次数。
这个并不是指字节大小,而是指DMA的传输次数,传输的字节大小由DMA_PeripheralDataSize
设置。
DMA传输数据时,从DMA_MemoryBaseAddr+0
地址开始放,直到DMA_MemoryBaseAddr+DMA_BufferSize-1
,此时DMA_CNDTR
变成0,传输结束。 -
DMA_PeripheralInc
:
如果配置为DMA_PeripheralInc_Enable
,使能外设地址自动递增功能,它设定DMA_CCR
寄存器的PINC
位的值;一般外设都是只有一个数据寄存器,所以一般不会使能该位。
-
DMA_MemoryInc
:
如果配置为DMA_MemoryInc_Enable
,使能存储器地址自动递增功能,它设定DMA_CCR
寄存器的 MINC 位的值;我们自定义的存储区一般都是存放多个数据的,所以要使能存储器地址自动递增功能。
-
DMA_PeripheralDataSize
:
外设数据宽度,可选字节 (8 位)、半字 (16 位) 和字 (32 位),它设定DMA_CCR
寄存器的PSIZE[1:0]
位的值。
-
DMA_MemoryDataSize
:
存储器数据宽度,可选字节 (8 位)、半字 (16 位) 和字 (32 位),它设定DMA_CCR
寄存器的MSIZE[1:0]
位的值。当外设和存储器之间传数据时,两边的数据宽度应该设置为一致大小。
-
DMA_Mode
:
DMA 传输模式选择,可选一次传输Normal
或者循环传输Circular
,它设定 DMA_CCR 寄存器的CIRC 位的值。例程我们的 ADC 采集是持续循环进行的,所以使用循环传输模式。
-
DMA_Priority
:
软件设置通道的优先级,有 4 个可选优先级分别为非常高、高、中和低,它设定DMA_CCR
寄存器的PL[1:0]
位的值。DMA 通道优先级只有在多个 DMA 通道同时使用时才有意义,如果是单个通道,优先级可以随便设置。
-
DMA_M2M
:
存储器到存储器模式,使用存储器到存储器时用到,设定DMA_CCR 的位 14 MEN2MEN
即可启动存储器到存储器模式。
(2)DMA结构体初始化
DMA_InitTypeDef DMA_InitStructure;// 开启DMA时钟RCC_AHBPeriphClockCmd(DMA_CLOCK, ENABLE);// 源数据地址DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ShuZu_YouShu; //数组有32个数,每个数都是一个字,且使用const定义(存储在FLASH)// 目标地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ShuZu_MeiShu; //数组有32个数,每个数都是一个字// 方向:外设到存储器(这里的外设是内部的FLASH) DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;// 传输大小 DMA_InitStructure.DMA_BufferSize = 32; //因为数组有32个数,所以设32// 外设(内部的FLASH)地址递增 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;// 内存地址递增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 外设数据单位 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //因为每个数大小都是一个字,所以宽度设为Word// 内存数据单位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //因为每个数大小都是一个字,所以宽度设为Word// DMA模式,一次或者循环模式DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //一次传输模式//DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 优先级:高 DMA_InitStructure.DMA_Priority = DMA_Priority_High;// 使能内存到内存的传输DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; //因为本次是FLASH传输到SRAM,所以是存储器到存储器// 配置DMA通道 DMA_Init(DMA_CHANNEL, &DMA_InitStructure);//清除DMA数据流传输完成标志位DMA_ClearFlag(DMA_FLAG_TC);// 使能DMADMA_Cmd(DMA_CHANNEL,ENABLE);
其中,
- 需开启DMA时钟才能使用DMA功能:
// 开启DMA时钟
RCC_AHBPeriphClockCmd(DMA_CLOCK, ENABLE);
ShuZu_YouShu
定义如下:
uint32_t ShuZu_YouShu[32]= {0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40,0x41424344,0x45464748,0x494A4B4C,0x4D4E4F50,0x51525354,0x55565758,0x595A5B5C,0x5D5E5F60,0x61626364,0x65666768,0x696A6B6C,0x6D6E6F70,0x71727374,0x75767778,0x797A7B7C,0x7D7E7F80};
- 需清除 DMA 标志位后再使用DMA功能,防止不必要的干扰:
//清除DMA数据流传输完成标志位DMA_ClearFlag(DMA_FLAG_TC);
(3)程序验证
DMA传输过后,在DEBUG
界面可以看到,ShuZu_YouShu
的数字传输到了ShuZu_MeiShu
中
2、DMA 存储器到外设模式实验
具体实验为 将数组中的数字 传输至 串口
(1)串口初始化
代码解释均放入注释中,正文不再复述
/*** @brief USART GPIO 配置,工作参数配置* @param 无* @retval 无*/
void USART_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 打开串口GPIO的时钟DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);// 打开串口外设的时钟DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);// 将USART Tx的GPIO配置为推挽复用模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);// 将USART Rx的GPIO配置为浮空输入模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);// 配置串口的工作参数// 配置波特率 为 115200USART_InitStructure.USART_BaudRate = 115200;// 配置 数据字长 为 8USART_InitStructure.USART_WordLength = USART_WordLength_8b;// 配置 停止位 为 1USART_InitStructure.USART_StopBits = USART_StopBits_1;// 配置 校验位 为 0USART_InitStructure.USART_Parity = USART_Parity_No ;// 配置硬件流控制USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// 配置工作模式,收发一起USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// 完成串口的初始化配置USART_Init(DEBUG_USARTx, &USART_InitStructure); // 使能串口USART_Cmd(DEBUG_USARTx, ENABLE);
}
(2)DMA结构体初始化
因为数据是从存储器到串口,所以设置存储器为源地址,串口的数据寄存器为目标地址。
要发送的数据有很多且都先存储在存储器中,则存储器地址指针递增;串口数据寄存器只有一个,则外设地址地址不变。
两边数据单位设置成一致,传输模式可选一次或者循环传输,只有一个 DMA 请求,优先级随便设。
最后调用 DMA_Init
函数把这些参数写到 DMA 的寄存器中,然后使能 DMA开始传输。
void USARTx_DMA_Config(void)
{DMA_InitTypeDef DMA_InitStructure;// 开启DMA时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);// 设置DMA源地址:串口数据寄存器地址*/DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;// 内存地址(要传输的变量的指针)DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ShuZu_YouShu;// 方向:从内存到外设 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;// 传输数量DMA_InitStructure.DMA_BufferSize = 5000; // 传输数量 设为 5000,这个数随便设,只要不超过数组大小就可// 外设地址不增 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 内存地址自增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;// 外设数据单位 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //因为每次传输1bit,所以设为Byte// 内存数据单位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //因为每次传输1bit,所以设为Byte// DMA模式,一次或者循环模式DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; //一次传输模式//DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 优先级:中 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; // 禁止内存到内存的传输DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;// 配置DMA通道 DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure); // 使能DMADMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
}
其中,
- 外设地址
DMA_PeripheralBaseAddr
为串口地址(需查阅开发手册),即:
// 外设寄存器地址
#define PERIPH_BASE ((uint32_t)0x40000000)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define USART1_BASE (APB2PERIPH_BASE + 0x3800)
#define USART_DR_ADDRESS (USART1_BASE+0x04)
ShuZu_YouShu
数组填充为A-Z
共26个字母,再加一个回车
:
/*填充将要发送的数据*/for(i=0; i < 5000; i++){ShuZu_YouShu[i] = 'A'+ i%27;if(ShuZu_YouShu[i] == '['){ShuZu_YouShu[i] = '\n';}}
(3)程序验证
使用USART_DMACmd
函数打开USART 的DMA请求。
/* USART1 向 DMA发出TX请求 */USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
它接收三个参数:
- 第一个参数用于设置串口外设,可以是
USART1/2/3
和UART4/5
这 5 个参数可选。 - 第二个参数设置串口的具体 DMA 请求,有串口发送请求
USART_DMAReq_Tx
和接收请求USART_DMAReq_Rx
可选。 - 第三个参数用于设置启动请求
ENABLE
或者关闭请求DISABLE
。
运行该函数后 USART
的DMA 发送传输就开始了,根据配置存储器的数据会发送到串口。
验证结果如下:
相关文章:

(STM32笔记)十二、DMA的基础知识与用法 第三部分
我用的是正点的STM32F103来进行学习,板子和教程是野火的指南者。 之后的这个系列笔记开头未标明的话,用的也是这个板子和教程。 DMA的基础知识与用法 三、DMA程序验证1、DMA 存储器到存储器模式实验(1)DMA结构体解释(2…...

品牌账号矩阵如何打造?来抄作业
在讲究全域营销的当下,目前企业都在各自搭建品牌矩阵号,以提升自己在不同渠道上的影响力。虽然不同平台之间有诸多细节值得深究,但也不妨碍我们先了解如何搭建品牌矩阵。接下来,就让我们一同来了解下该如何搭建。 一、一个主账号 …...

基于vue的商城小程序的毕业设计与实现(源码及报告)
环境搭建 ☞☞☞ Vue入手篇(一),防踩雷(全网最详细教程)_vue force-CSDN博客 目录 一、功能介绍 二、登录注册功能 三、首页 四、项目截图 五、源码获取 一、功能介绍 用户信息展示:页面顶部设有用户头像和昵称展示区,方便用户识别…...

NineData云原生智能数据管理平台新功能发布|2024年12月版
本月发布 7 项更新,其中重点发布 2 项、功能优化 5 项。 重点发布 数据库 Devops - Oracle 非表对象支持可视化创建与管理 Oracle 非表对象,包括视图(View)、包(Package)、存储过程(Procedur…...

【Vue.js 组件化】高效组件管理与自动化实践指南
文章目录 摘要引言组件命名规范与组织结构命名规范目录组织 依赖管理工具自动化组件文档生成构建自动引入和文档生成的组件化体系代码结构自动引入组件配置使用 Storybook 展示组件文档自动生成 代码详解QA 环节总结参考资料 摘要 在现代前端开发中,组件化管理是 V…...
Clojure语言的并发编程
Clojure语言的并发编程 引言 在现代软件开发中,并发编程成为了处理多个任务、提高应用效率和响应速度的重要手段。尤其是在多核处理器逐渐成为主流的今天,如何高效利用这些计算资源是每个开发者面临的挑战。Clojure作为一种函数式编程语言,…...

RabbitMQ-SpringAMQP使用介绍
RabbitMQ 1. Spring AMQP1.1 引入依赖1.2 消息发送1.3 消息接收1.4 WorkQueue模型1.4.1 实例代码1.4.2 能者多劳1.4.3 总结 1.5交换机1.6 Fanout交换机(广播)1.7 Direct交换机(订阅)1.8 Topic交换机(通配符订阅&#x…...

ASP.NET Core 中服务生命周期详解:Scoped、Transient 和 Singleton 的业务场景分析
前言 在 ASP.NET Core 中,服务的生命周期直接影响应用的性能和行为。通过依赖注入容器 (Dependency Injection, DI),我们可以为服务定义其生命周期:Scoped、Transient 和 Singleton。本文将详细阐述这些生命周期的区别及其在实际业务中的应用…...
c语言----------小知识
1 system函数的使用 #include <stdlib.h> int system(const char *command); 功能:在已经运行的程序中执行另外一个外部程序 参数:外部可执行程序名字 返回值: 成功:0 失败:任意数字示例代码: #inc…...
React Context用法总结
1. 基本概念 1.1 什么是 Context Context 提供了一种在组件树中共享数据的方式,而不必通过 props 显式地逐层传递。它主要用于共享那些对于组件树中许多组件来说是"全局"的数据。 1.2 基本用法 // 1. 创建 Context const ThemeContext React.createC…...

[笔记] 使用 Jenkins 实现 CI/CD :从 GitLab 拉取 Java 项目并部署至 Windows Server
随着软件开发节奏的加快,持续集成(CI)和持续部署(CD)已经成为确保软件质量和加速产品发布的不可或缺的部分。Jenkins作为一款广泛使用的开源自动化服务器,为开发者提供了一个强大的平台来实施这些实践。然而…...

腾讯云AI代码助手编程挑战赛-如意
作品简介 《如意》是一款结合腾讯云AI代码助手生成的、集智能问答、知识学习和生活助手功能于一体的应用,在通过先进的AI技术提升用户的工作效率、学习效果和生活质量。无论是解答疑难问题、提供专业建议,还是帮助规划日程、提升技能,它都能…...

TAS测评倍智题库 | 益丰大药房2025年中高层测评BA商业推理测评真题考什么?
您好!您已被邀请参加360评估。您的评估与反馈将有助于被评估人更深入地了解个人情况,发现个人优势和潜在风险。请您秉持公正、开放的心态进行评估。请尽快完成评估,在此衷心感谢您的配合与支持! 相关事宜: 请您在…...

2025 First LOOK! CnosDB 新版本 2.4.3.1 发布
🔹 版本号:2.4.3.1 🔹 发布日期:2024年11月05日 功能优化 简化编解码器错误定义 #2368 删除不必要的const DEFAULT_* #2378 添加 wal 压缩检查 #2377 移除 page reader #2380 创建配额 #2367 减少内存复制和计算 #2384 构…...

PyMysql 01|(包含超详细项目实战)连接数据库、增删改查、异常捕获
目录 一、数据库操作应用场景 二、安装PyMysql 三、事务的概念 四、数据库的准备 五、PyMysql连接数据库 1、建立连接方法 2、入门案例 六、PyMysql操作数据库 1、数据库查询 1️⃣查询操作流程 2️⃣cursor游标 3️⃣查询常用方法 4️⃣案例 5️⃣异常捕获 …...

Android14上使用libgpiod[gpioinfo gpioget gpioset ...]
环境 $ cat /etc/os-release NAME="Ubuntu" VERSION="20.04.5 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.5 LTS" VERSION_ID="20.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="…...

网络安全 信息收集入门
1.信息收集定义 信息收集是指收集有关目标应用程序和系统的相关信息。这些信息可以帮助攻击者了解目标系统的架构、技术实现细节、运行环境、网络拓扑结构、安全措施等方面的信息,以便我们在后续的渗透过程更好的进行。 2.收集方式-主动和被动收集 ①收集方式不同…...
修改sshd默认配置,提升安全
对于Linux服务器,特别是暴露在公网的服务器,会经常被人扫描、探测和攻击。包括通过ssh访问登录攻击。对此,对默认的sshd配置进行调整,提升安全。 下面以CentOS 7.9为例说明: 一、常见安全措施 以root用户编辑vim /e…...
Clojure语言的面向对象编程
Clojure语言的面向对象编程 引言 Clojure是一种现代的Lisp方言,它特别强调函数式编程,Immutable数据结构和强大的并发能力。然而,很多人可能会问:Clojure支持面向对象编程吗?虽然Clojure没有像Java或C那样的传统类和…...

spring boot启动源码分析(三)之Environment准备
上一篇《spring-boot启动源码分析(二)之SpringApplicationRunListener》 环境介绍: spring boot版本:2.7.18 主要starter:spring-boot-starter-web 本篇开始讲启动过程中Environment环境准备,Environment是管理所有…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...