STM32的DMA技术介绍

DMA(Direct Memory Access,直接内存访问) 是一种允许外设直接与系统内存进行数据传输,而无需经过CPU的技术。在STM32微控制器中,DMA技术极大地提高了数据传输效率,降低了CPU的负担,从而提升系统整体性能。

1. DMA的基本概念
  • 工作原理:DMA控制器能够在外设和内存之间进行数据传输,而无需CPU介入。CPU只需初始化传输参数,DMA控制器便会自动完成数据传输任务。

  • 优点

    • 减轻CPU负担:CPU无需参与数据传输过程,可以处理其他任务,提高系统响应速度。
    • 高效的数据传输:DMA能够在总线空闲时进行数据传输,提高总线利用率。
    • 降低功耗:减少CPU的工作量,有助于降低系统功耗,尤其在低功耗应用中尤为重要。
2. STM32中的DMA模块

STM32系列微控制器通常集成多个DMA控制器,每个控制器包含多个DMA通道。不同的STM32系列(如F1、F4、L4等)在DMA模块的数量和功能上可能有所不同,但基本原理相似。

  • DMA控制器:负责管理多个DMA通道,协调数据传输任务。
  • DMA通道:每个通道可以独立配置,用于特定的外设或数据传输任务。
3. DMA的工作模式

STM32的DMA支持多种工作模式,以适应不同的应用需求:

  • 内存到内存模式(Memory-to-Memory):在两个内存区域之间传输数据,不经过外设。
  • 外设到内存模式(Peripheral-to-Memory):从外设(如USART、ADC)读取数据并存储到内存。
  • 内存到外设模式(Memory-to-Peripheral):从内存读取数据并传输到外设(如USART、DAC)。

此外,DMA还支持:

  • 循环模式(Circular Mode):数据传输完成后自动重新开始,适用于需要持续数据流的应用,如音频采集。
  • 双缓冲模式(Double Buffer Mode):使用两个内存缓冲区,交替进行数据传输,提高数据处理效率。
4. DMA的配置步骤

在STM32中配置DMA通常包括以下步骤:

  1. 启用DMA时钟:通过配置相应的时钟寄存器,确保DMA控制器的时钟信号开启。

    __HAL_RCC_DMA1_CLK_ENABLE();
    
  2. 配置DMA通道

    • 选择通道:根据外设选择合适的DMA通道。
    • 配置传输方向:内存到外设、外设到内存或内存到内存。
    • 数据大小:设置源和目的地的数据宽度(如8位、16位、32位)。
    • 传输模式:如普通模式或循环模式。
    • 优先级:设置通道优先级,决定在多个通道同时请求时的处理顺序。
    DMA_HandleTypeDef hdma;
    hdma.Instance = DMA1_Stream1;
    hdma.Init.Channel = DMA_CHANNEL_4;
    hdma.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma.Init.MemInc = DMA_MINC_ENABLE;
    hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma.Init.Mode = DMA_NORMAL;
    hdma.Init.Priority = DMA_PRIORITY_LOW;
    HAL_DMA_Init(&hdma);
    
  3. 链接DMA与外设:将DMA通道与具体的外设进行绑定,如USART、ADC等。

    __HAL_LINKDMA(&huart, hdmatx, hdma);
    
  4. 配置中断(可选):根据需要配置DMA传输完成、半完成或错误中断,便于在传输完成后进行相应处理。

    HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
    
  5. 启动DMA传输:调用相应的HAL库函数或直接操作寄存器启动数据传输。

    HAL_DMA_Start_IT(&hdma, (uint32_t)source, (uint32_t)destination, data_length);
    
5. DMA在常见外设中的应用
  • USART(串口通信):通过DMA进行数据的发送和接收,可以实现高速数据传输,减少CPU的干预。

    HAL_UART_Transmit_DMA(&huart, buffer, length);
    HAL_UART_Receive_DMA(&huart, buffer, length);
    
  • ADC(模数转换器):使用DMA自动将ADC转换结果存储到内存,适合采集大量连续数据,如传感器数据采集。

    HAL_ADC_Start_DMA(&hadc, buffer, length);
    
  • SPI/I2C:通过DMA进行高速数据传输,适用于需要大量数据交换的应用,如存储设备通信。

6. DMA与中断的协同工作

虽然DMA能够独立完成数据传输,但通常会与中断机制结合使用,以实现更灵活和高效的系统设计。例如,当DMA传输完成时,可以触发中断,通知CPU进行后续处理,如数据解析或下一步操作。

void DMA1_Stream1_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma);
}

void HAL_DMA_TxCpltCallback(DMA_HandleTypeDef *hdma)
{
    // 传输完成后的处理
}
7. DMA的注意事项
  • 内存对齐:某些DMA传输要求源地址和目的地址对齐,避免数据错误。
  • 缓存一致性:在使用带缓存的系统中,需确保缓存与内存的一致性,防止数据传输错误。
  • 优先级管理:合理设置DMA通道的优先级,避免高优先级通道频繁占用总线,导致低优先级任务延迟。
  • 资源冲突:确保多个DMA通道之间没有资源冲突,如同一外设的多次访问需合理分配通道。
8. 实际应用示例

使用DMA进行USART数据传输

以下是一个使用DMA进行USART数据发送和接收的简单示例:

  1. 初始化USART和DMA

    // USART初始化代码
    MX_USART2_UART_Init();
    
    // DMA初始化代码
    MX_DMA_Init();
    
  2. 发送数据

    uint8_t txBuffer[] = "Hello DMA!";
    HAL_UART_Transmit_DMA(&huart2, txBuffer, sizeof(txBuffer));
    
  3. 接收数据

    uint8_t rxBuffer[10];
    HAL_UART_Receive_DMA(&huart2, rxBuffer, sizeof(rxBuffer));
    
  4. 处理传输完成中断

    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
    {
        // 发送完成后的处理
    }
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
        // 接收完成后的处理
    }
    
9. 总结

DMA技术在STM32微控制器中扮演着至关重要的角色,通过高效的数据传输机制,显著提升了系统性能和响应速度。在实际应用中,合理配置和使用DMA,可以使系统设计更加优化,满足复杂和高性能的应用需求。掌握DMA的工作原理、配置方法及其在不同外设中的应用,是深入理解和高效使用STM32微控制器的重要步骤。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

谷歌发布了日语版的 Gemma2 模型——gemma-2-2b-jpn-it

Gemma 是一系列同类最佳的开放式模型,其灵感和技术源自 Gemini 系列模型。 它们是具有开放权重的文本到文本、纯解码器大型语言模型。 Gemma 模型非常适合各种文本生成任务,包括问题解答、摘要和推理。 Gemma-2-JPN 是一个针对日语文本进行微调的 Gemma…

使用微服务Spring Cloud集成Kafka实现异步通信

在微服务架构中,使用Spring Cloud集成Apache Kafka来实现异步通信是一种常见且高效的做法。Kafka作为一个分布式流处理平台,能够处理高吞吐量的数据,非常适合用于微服务之间的消息传递。 微服务之间的通信方式包括同步通信和异步通信。 1&a…

【CTF Web】Pikachu CSRF(get) Writeup(CSRF+GET请求+社会工程学)

CSRF(跨站请求伪造)概述 Cross-site request forgery 简称为“CSRF”,在CSRF的攻击场景中攻击者会伪造一个请求(这个请求一般是一个链接),然后欺骗目标用户进行点击,用户一旦点击了这个请求,整个攻击就完成…

vmstat命令:系统性能监控

一、命令简介 ​vmstat​ 是一种在类 Unix 系统上常用的性能监控工具,它可以报告虚拟内存统计信息,包括进程、内存、分页、块 IO、陷阱(中断)和 CPU 活动等。 ‍ 二、命令参数 2.1 命令格式 vmstat [选项] [ 延迟 [次数] ]2…

docker快速上手

一个轻量的虚拟机,让程序员不再纠结于环境部署,更多集中于代码编写,基础建设,开发 作用: 打包:把你软件运行所需的所有东西打包到一起 分发:把你打包好的“安装包”上传到一个镜像仓库&#…

渲染技术的教育普及,塑造未来视觉艺术与技术的璀璨星辰

在数字时代的浪潮中,渲染技术作为连接创意与现实的桥梁,正以前所未有的速度推动着视觉艺术与技术领域的融合与发展。从电影特效的震撼呈现到游戏世界的细腻构建,从广告设计的视觉冲击力到建筑设计方案的直观展示,渲染技术无处不在…

css 简单网页布局——浮动(一)

1. 三种布局方式 1.1 标准流 1.2 浮动的使用 1.3 简述浮动 1.3.1 浮动三大特性 <style>.out {border: 1px red solid;width: 1000px;height: 500px;}.one {background-color: aquamarine;width: 200px;height: 100px;}.two {background-color: blueviolet;width: 200px;h…

『网络游戏』窗口基类【06】

创建脚本&#xff1a;WindowRoot.cs 编写脚本&#xff1a; 修改脚本&#xff1a;LoginWnd.cs 修改脚本&#xff1a;LoadingWnd.cs 修改脚本&#xff1a;ResSvc.cs 修改脚本&#xff1a;LoginSys.cs 运行项目 - 功能不变 本章结束

【AI知识点】批归一化(Batch Normalization)

批归一化&#xff08;Batch Normalization&#xff0c;BN&#xff09; 是一种用于加速神经网络训练并提高模型稳定性的方法&#xff0c;通过在每一层对神经网络中的激活值进行标准化&#xff0c;使得每一层的输入保持在一个稳定的分布中&#xff0c;从而缓解梯度消失和梯度爆炸…

Chromium 搜索引擎功能浅析c++

地址栏输入&#xff1a;chrome://settings/searchEngines 可以看到 有百度等数据源&#xff0c;那么如何调整其顺序呢&#xff0c;此数据又存储在哪里呢&#xff1f; 1、浏览器初始化搜索引擎数据来源在 components\search_engines\prepopulated_engines.json // Copyright …

机器学习-支撑向量机SVM

Support Vector Machine 离分类样本尽可能远 Soft Margin SVM scikit-learn中的SVM 和kNN一样&#xff0c;要做数据标准化处理&#xff01; 涉及距离&#xff01; 加载数据集 import numpy as np import matplotlib.pyplot as plt from sklearn import datasetsiris datas…

Debezium日常分享系列之:Debezium 3.0.0.Final发布

Debezium日常分享系列之&#xff1a;Debezium 3.0.0.Final发布 Debezium 核心的变化需要 Java 17基于Kafka 3.8 构建废弃的增量信号字段的删除每个表的详细指标 MariaDB连接器的更改版本 11.4.3 支持 MongoDB连接器的更改MongoDB sink connector MySQL连接器的改变MySQL 9MySQL…

【图论】迪杰特斯拉算法

文章目录 迪杰特斯拉算法主要特点基本思想算法步骤示例 实现迪杰斯特拉算法基本步骤算法思路 总结 迪杰特斯拉算法 迪杰特斯拉算法是由荷兰计算机科学家艾兹赫尔迪杰特斯拉&#xff08;Edsger W. Dijkstra&#xff09;在1956年提出的&#xff0c;用于解决单源最短路径问题的经…

命令行py脚本——Linux下方便快捷地运行*.py脚本

命令行参数传递&#xff0c;shell批指令和命令别名。 (笔记模板由python脚本于2024年10月08日 12:25:54创建&#xff0c;本篇笔记适合喜欢python和Linux的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣…

Docker:快速部署

docker安装&#xff1a; ​‌​‬&#xfeff;​&#xfeff;⁠​‍‬​‍‬‬‌​‬‬‬​&#xfeff;⁠​‍​​‌‬‌&#xfeff;​​​​​​‌​​​​⁠​‍⁠‌安装Docker - 飞书云文档 (feishu.cn) docker命令解读 docker run -d \ > --name mysql \ > -p 33…

【bug】finalshell向远程主机拖动windows快捷方式导致卡死

finalshell向远程主机拖动windows快捷方式导致卡死 问题描述 如题&#xff0c;作死把桌面的快捷方式拖到了finalshell连接的服务器面板中&#xff0c;导致finalshell没有响应&#xff08;小概率事件&#xff0c;有时会触发&#xff09; 解决 打开任务管理器查看finalshell进…

SpringBoot Jar 包加密防止反编译

今天看到了一个说明jar包加密的实现方式&#xff0c;特意试了下效果&#xff0c;并下载了插件源码及实现源码查看了下子&#xff0c;感兴趣的可以在最后得到gitee地址。 SpringBoot 程序 Jar 包加密的方式&#xff0c;通过代码加密可以实现无法反编译。应用场景就是当需要把公司…

RK3568笔记六十四:SG90驱动测试

若该文为原创文章,转载请注明原文出处。 前面有测试过PWM驱动,现在使用两种方式来产生PWM驱动SG90,实现舵机旋转任意角度 方法一:使用硬件PWM 方法二:使用高精度定时器,GPIO模拟PWM. 一、PWM子系统框架 二、SG90控制方法 舵机的控制需要MCU产生一个周期为20ms的脉冲信号…

(Linux驱动学习 - 8).信号异步通知

一.异步通知简介 1.信号简介 信号类似于我们硬件上使用的“中断”&#xff0c;只不过信号是软件层次上的。算是在软件层次上对中断的一种模拟&#xff0c;驱动可以通过主动向应用程序发送信号的方式来报告自己可以访问了&#xff0c;应用程序获取到信号以后就可以从驱动设备中…

【JavaEE】【多线程】Thread类讲解

目录 Thread构造方法Thread 的常见属性创建一个线程获取当前线程引用终止一个线程使用标志位使用自带的标志位 等待一个线程线程休眠线程状态线程安全线程不安全原因总结解决由先前线程不安全问题例子 Thread构造方法 方法说明Thread()创建线程对象Thread(Runnable target)使用…