首页 > 其他分享 >STM32相关知识——DMA的基本概念与工作原理详解

STM32相关知识——DMA的基本概念与工作原理详解

时间:2024-11-21 17:48:16浏览次数:3  
标签:DMA STM32 传输 详解 内存 数据传输 数据 外设

STM32相关知识——DMA的基本概念与工作原理详解

目录

  1. 什么是DMA
  2. DMA的作用
  3. DMA与CPU的区别
  4. DMA的工作原理
  5. STM32中DMA的应用
  6. 数学公式
  7. DMA的优缺点
  8. DMA的配置与使用
  9. 高级DMA特性
  10. 常见问题与调试
  11. 代码示例
  12. 结语

什么是DMA

DMA(Direct Memory Access,直接内存存取)是一种计算机系统中用于高效数据传输的技术。它允许特定硬件子系统在不经过CPU干预的情况下,直接在内存和外设之间传输数据。通过DMA,数据传输过程由DMA控制器管理,减少了CPU的负担,提高了系统的整体性能和响应速度。

DMA的作用

  • 减轻CPU负担:在数据传输过程中,CPU无需参与数据的搬移,只需初始化传输参数,之后DMA控制器自动完成数据的搬移任务。
  • 提高数据传输效率:DMA能够高效地处理大规模数据传输,尤其适合需要高速、连续数据传输的应用场景。
  • 支持并行操作:DMA可以与CPU同时工作,实现多任务并行处理,提高系统的吞吐量。
  • 降低能耗:减少CPU的参与度,可以降低系统的功耗,尤其在低功耗应用中具有重要意义。

DMA与CPU的区别

特性DMACPU
控制方式硬件控制软件控制
数据传输自动化,独立于CPU需要CPU指令进行数据传输
负载专用硬件,专门处理数据传输通用处理器,处理各种计算任务
并行处理能力可以与CPU并行工作单线程或多线程,但受限于核心数量
数据吞吐量高吞吐量,适合大规模数据传输受限于指令执行速度,适合小规模数据传输

DMA的工作原理

DMA控制器

DMA控制器是专门用于管理数据传输的硬件模块。它通过配置传输源地址、目标地址、传输大小、传输方向等参数,自动完成数据在内存和外设之间的搬移。STM32微控制器通常内置多个DMA控制器,每个控制器包含多个通道(Channel),每个通道可以独立配置,支持同时处理多个数据传输任务。

数据传输流程

  1. 初始化:CPU配置DMA控制器,设置源地址、目标地址、数据大小、传输方向等参数。
  2. 启动传输:CPU启动DMA传输,DMA控制器开始执行数据搬移任务。
  3. 数据搬移:DMA控制器按照配置,从源地址读取数据,并写入目标地址,直至完成整个数据块的传输。
  4. 中断通知:传输完成后,DMA控制器向CPU发送中断信号,通知传输结束,CPU可进行后续处理。

DMA传输模式

DMA支持多种传输模式,以适应不同的应用需求:

  • 内存到外设(Memory to Peripheral):数据从内存传输到外设,如UART发送数据。
  • 外设到内存(Peripheral to Memory):数据从外设传输到内存,如UART接收数据。
  • 内存到内存(Memory to Memory):数据在内存之间传输,适用于数据块的搬移或复制。

优先级和通道管理

DMA控制器通常包含多个通道,每个通道可以独立配置,用于不同的外设或内存区域。每个通道可以设置不同的优先级,决定在多个传输请求同时到达时的处理顺序。优先级通常分为高、中、低等级别,确保关键数据传输能够优先完成。

STM32中DMA的应用

外设与内存之间的数据传输

在STM32微控制器中,DMA广泛应用于各种外设与内存之间的数据传输,如:

  • USART:通过DMA进行数据的发送和接收,提高串口通信的效率。
  • SPI:利用DMA进行高速数据传输,适用于高速外围设备的数据交互。
  • I2C:通过DMA实现高效的数据传输,适用于多设备通信场景。
  • ADC/DAC:利用DMA进行连续数据采集和输出,适用于实时数据处理应用。

内存与内存的数据传输

DMA不仅可以在内存与外设之间进行数据传输,还支持内存与内存之间的数据搬移。这在需要快速复制或移动大量数据的应用中尤为重要,如图像处理、数据缓存等。

示例应用场景

  • 音频处理:通过DMA将音频数据从ADC传输到内存,再由DAC输出,实现实时音频处理。
  • 网络通信:高速数据包通过DMA传输到内存,减轻CPU的网络处理负担,提高网络吞吐量。
  • 显示刷新:将图像数据通过DMA传输到LCD控制器,提高显示刷新速度,确保图像的流畅显示。
  • 数据采集系统:利用DMA进行多通道ADC的数据采集,实现高精度、高速的数据采集。

数学公式

数据传输速率计算

数据传输速率(R)表示单位时间内传输的数据量,计算公式如下:

R = N × D T R = \frac{N \times D}{T} R=TN×D​

其中:

  • R R R 为数据传输速率(位/秒)
  • N N N 为传输的数据单元数量
  • D D D 为每个数据单元的位数
  • T T T 为传输所需的时间(秒)

示例:传输1024个字节的数据,传输时间为0.01秒。

R = 1024 × 8 0.01 = 819200  位/秒 R = \frac{1024 \times 8}{0.01} = 819200 \text{ 位/秒} R=0.011024×8​=819200 位/秒

总线带宽计算

总线带宽(BW)表示总线在单位时间内能够传输的数据量,计算公式如下:

B W = f × b BW = f \times b BW=f×b

其中:

  • f f f 为总线频率(Hz)
  • b b b 为总线的宽度(位)

示例:一个32位宽,总线频率为100MHz的总线。

B W = 100 × 1 0 6 × 32 = 3.2 × 1 0 9  位/秒 = 400  MB/s BW = 100 \times 10^6 \times 32 = 3.2 \times 10^9 \text{ 位/秒} = 400 \text{ MB/s} BW=100×106×32=3.2×109 位/秒=400 MB/s

传输延迟计算

传输延迟( T l a t T_{lat} Tlat​)表示数据从源地址到目标地址所需的时间,考虑到总线带宽和数据量,计算公式如下:

T l a t = N × D B W T_{lat} = \frac{N \times D}{BW} Tlat​=BWN×D​

其中:

  • N N N 为传输的数据单元数量
  • D D D 为每个数据单元的位数
  • B W BW BW 为总线带宽(位/秒)

示例:传输1MB( 8 × 1 0 6 8 \times 10^6 8×106 位)的数据,总线带宽为400 MB/s( 3.2 × 1 0 9 3.2 \times 10^9 3.2×109 位/秒)。

T l a t = 8 × 1 0 6 3.2 × 1 0 9 = 2.5 × 1 0 − 3  秒 = 2.5  毫秒 T_{lat} = \frac{8 \times 10^6}{3.2 \times 10^9} = 2.5 \times 10^{-3} \text{ 秒} = 2.5 \text{ 毫秒} Tlat​=3.2×1098×106​=2.5×10−3 秒=2.5 毫秒

DMA的优缺点

优点

  • 高效的数据传输:无需CPU干预,减少数据传输延迟,提高传输效率。
  • 降低CPU负载:释放CPU资源用于其他计算任务,提高系统响应速度和多任务处理能力。
  • 支持多通道并行传输:DMA控制器支持多个通道,可以同时处理多个数据传输任务,提高系统的吞吐量。
  • 节省功耗:减少CPU的参与,降低系统的功耗,适用于低功耗应用。

缺点

  • 复杂的配置:需要详细配置DMA控制器和相关外设,增加系统设计的复杂性。
  • 资源占用:DMA通道数量有限,可能成为系统设计的瓶颈,尤其在需要多个并行传输的应用中。
  • 调试困难:硬件级的数据传输可能导致调试复杂性增加,尤其在多通道和复杂传输模式下。
  • 数据一致性问题:在多任务环境下,需要确保DMA传输过程中数据的一致性和完整性,避免数据冲突。

DMA的配置与使用

DMA初始化步骤

在STM32中,配置DMA通常涉及以下步骤:

  1. 使能DMA时钟:通过RCC(时钟控制)使能对应的DMA控制器时钟。
  2. 配置DMA通道:设置源地址、目标地址、数据长度、数据宽度、传输方向、优先级等参数。
  3. 配置外设:使能外设的DMA功能,如USART的DMA接收或发送。
  4. 配置中断:配置DMA传输完成中断,编写中断服务程序处理传输完成后的操作。
  5. 启用DMA传输:启动DMA通道,开始数据传输。

配置DMA参数

配置DMA时,需要设置多个参数以确保数据传输的正确性和效率,包括:

  • 源地址(Source Address):数据传输的源地址,可以是内存地址或外设数据寄存器地址。
  • 目标地址(Destination Address):数据传输的目标地址,可以是内存地址或外设数据寄存器地址。
  • 数据方向(Data Direction):数据传输的方向,如内存到外设、外设到内存或内存到内存。
  • 数据长度(Data Length):传输的数据量,通常以字节为单位。
  • 数据宽度(Data Width):传输的数据宽度,如字节(8位)、半字(16位)或字(32位)。
  • 传输模式(Transfer Mode):如正常模式、循环模式或双缓冲模式。
  • 优先级(Priority):DMA通道的优先级,决定多个传输请求时的处理顺序。
  • 存储器增量模式(Memory Increment Mode):传输过程中源或目标地址是否递增。
  • 外设增量模式(Peripheral Increment Mode):传输过程中外设地址是否递增。
  • FIFO模式(FIFO Mode):是否启用FIFO缓冲,提高传输效率。

启动DMA传输

配置完成后,通过启用DMA通道,启动数据传输。传输过程中,DMA控制器自动按照配置的参数进行数据搬移,直至传输完成。

处理中断

传输完成后,DMA控制器会触发中断,通知CPU传输已完成。中断服务程序(ISR)需要清除中断标志,并执行后续处理,如数据处理、缓冲区切换等。

高级DMA特性

循环模式

循环模式(Circular Mode)允许DMA在完成一次传输后,自动重新开始传输,形成循环传输。这在需要连续传输数据的应用中非常有用,如音频采集、实时数据监控等。

特点

  • 无需重新配置:传输完成后,DMA自动重新开始,无需CPU干预。
  • 适用于循环缓冲区:可以与双缓冲区结合使用,实现无缝的数据传输。

双缓冲模式

双缓冲模式(Double Buffer Mode)允许DMA在传输过程中使用两个缓冲区,交替进行数据传输和处理。这样可以避免数据传输和处理之间的冲突,提高系统的效率。

特点

  • 无缝数据传输:一个缓冲区用于数据传输,另一个缓冲区用于数据处理,避免数据丢失。
  • 提高系统吞吐量:同时进行传输和处理,提高整体系统的吞吐量。

FIFO模式

FIFO模式(First In First Out Mode)允许DMA使用FIFO缓冲区,提升数据传输的效率。FIFO模式可以减少数据传输过程中的等待时间,提高传输速率。

特点

  • 提高传输效率:通过缓冲区减少数据传输的等待时间。
  • 支持突发传输:适合高速数据传输需求,如图像数据处理。

常见问题与调试

DMA传输失败的原因

  1. 时钟未使能:DMA控制器或相关外设的时钟未正确配置。
  2. 地址配置错误:源地址或目标地址配置错误,导致数据无法正确传输。
  3. 数据长度错误:传输的数据长度配置不正确,导致传输中断或数据丢失。
  4. 优先级冲突:多个DMA通道优先级配置不当,导致传输冲突。
  5. 外设未启用DMA功能:外设的DMA功能未正确启用,导致数据传输无法启动。

如何调试DMA传输

  1. 检查时钟配置:确保DMA控制器和相关外设的时钟已正确使能。
  2. 验证地址配置:确认源地址和目标地址是否正确,确保数据能正确读取和写入。
  3. 检查数据长度:确保传输的数据长度与实际数据量匹配,避免数据溢出或不足。
  4. 监控中断状态:通过调试工具监控DMA中断标志,确定传输是否成功完成。
  5. 使用示波器或逻辑分析仪:监测数据传输信号,验证数据传输的正确性和稳定性。
  6. 逐步调试:逐步配置和测试每个DMA参数,确保每个配置步骤正确无误。

代码示例

STM32 DMA初始化代码

以下示例代码展示了如何在STM32F4系列微控制器中初始化DMA,以实现USART2的发送功能。

#include "stm32f4xx.h"

#define BUFFER_SIZE 1024
uint8_t txBuffer[BUFFER_SIZE];

// DMA2 Stream7 for USART2_TX

void DMA_Init(void) {
    // 1. 使能DMA2时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    
    // 2. DMA配置结构体初始化
    DMA_InitTypeDef DMA_InitStruct;
    DMA_StructInit(&DMA_InitStruct);
    
    // 3. 配置DMA通道
    DMA_InitStruct.DMA_Channel = DMA_Channel_4; // USART2_TX对应通道
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR; // 外设数据寄存器地址
    DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)txBuffer; // 内存地址
    DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral; // 数据传输方向
    DMA_InitStruct.DMA_BufferSize = BUFFER_SIZE; // 数据传输长度
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不递增
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址递增
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 内存数据宽度
    DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; // 传输模式
    DMA_InitStruct.DMA_Priority = DMA_Priority_High; // 优先级
    DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable; // FIFO模式禁用
    DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; // FIFO阈值
    DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single; // 内存突发传输
    DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 外设突发传输
    
    // 4. 初始化DMA2_Stream7
    DMA_Init(DMA2_Stream7, &DMA_InitStruct);
    
    // 5. 使能DMA传输完成中断
    DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);
    
    // 6. 配置NVIC中断优先级
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = DMA2_Stream7_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    
    // 7. 启用DMA通道
    DMA_Cmd(DMA2_Stream7, ENABLE);
}

数据传输代码

以下示例代码展示了如何使用DMA进行USART2的数据发送。

#include "stm32f4xx.h"
#include <string.h>

extern uint8_t txBuffer[];
#define BUFFER_SIZE 1024

void USART2_DMA_Send(uint8_t *data, uint16_t size) {
    // 1. 检查DMA通道是否空闲
    if (DMA_GetFlagStatus(DMA2_Stream7, DMA_FLAG_TCIF7)) {
        // 2. 清除传输完成标志
        DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7);
        
        // 3. 复制数据到txBuffer
        memcpy(txBuffer, data, size);
        
        // 4. 配置DMA传输大小
        DMA2_Stream7->NDTR = size;
        
        // 5. 启动DMA传输
        DMA_Cmd(DMA2_Stream7, ENABLE);
    }
}

中断服务程序代码

以下示例代码展示了DMA传输完成后的中断服务程序。

#include "stm32f4xx.h"

void DMA2_Stream7_IRQHandler(void) {
    // 检查传输完成中断标志
    if (DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7)) {
        // 清除中断标志
        DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7);
        
        // 传输完成后的处理
        // 例如,设置标志位通知主程序
        // 或者开始下一个传输
    }
}

简要解读

上述代码展示了如何在STM32F4系列微控制器中配置和使用DMA进行USART2的数据发送。

  1. DMA初始化:
  • 使能DMA时钟:通过RCC_AHB1PeriphClockCmd函数使能DMA2的时钟。
  • 配置DMA通道:设置DMA通道的源地址、目标地址、传输方向、数据长度、数据宽度等参数。
  • 中断配置:使能DMA传输完成中断,并配置NVIC中断优先级。
  • 启动DMA通道:通过DMA_Cmd函数启用DMA2_Stream7,准备进行数据传输。
  1. 数据传输:
  • 检查DMA状态:在发送数据前,检查DMA传输完成标志,确保DMA通道空闲。
  • 数据复制:将待发送的数据复制到txBuffer缓冲区。
  • 配置传输大小:设置DMA传输的数据长度。
  • 启动传输:通过DMA_Cmd函数启动DMA传输。
  1. 中断服务程序:
  • 中断处理:在DMA传输完成后,触发中断服务程序,清除中断标志,并执行后续处理,如通知主程序传输完成或开始下一次传输。

结语

本文详细介绍了STM32微控制器中DMA(Direct Memory Access,直接内存存取)的基本概念、作用、工作原理及其在实际应用中的配置与使用方法。通过深入解析DMA的工作机制、传输模式、优缺点以及高级特性,帮助读者全面理解DMA在嵌入式系统中的重要性和应用价值。

DMA作为一种高效的数据传输机制,在处理大规模数据传输、实时数据采集和高吞吐量应用中发挥着不可替代的作用。掌握DMA的配置与使用,不仅能够优化系统性能,还能提高开发效率,为复杂嵌入式系统的设计提供强有力的支持。

标签:DMA,STM32,传输,详解,内存,数据传输,数据,外设
From: https://blog.csdn.net/qq_44648285/article/details/143950702

相关文章

  • STM32定时器知识——看门狗详解
    STM32定时器知识——看门狗详解目录引言STM32看门狗概述看门狗的工作原理看门狗的主要组成4.1独立看门狗(IWDG)4.2窗口看门狗(WWDG)看门狗的主要参数5.1时钟源5.2预分频器5.3重载值看门狗的配置步骤6.1配置独立看门狗(IWDG)6.2配置窗口看门狗(WWDG)看门狗的数学公式......
  • 从0开始学习Linux——Shell编程详解【04】
     期目录:从0开始学习Linux——简介&安装从0开始学习Linux——搭建属于自己的Linux虚拟机从0开始学习Linux——文本编辑器从0开始学习Linux——Yum工具从0开始学习Linux——远程连接工具从0开始学习Linux——文件目录从0开始学习Linux——网络配置从0开始学习Linux——......
  • Day35--static关键字详解
    Day35--static关键字详解示例:packagecom.liu.oop.demo07;//staticpublicclassStudent{privatestaticintage;//静态的变量privatedoublescore;//非静态的变量publicstaticvoidmain(String[]args){Students1=newS......
  • Baichuan2 模型详解,附实验代码复现
    简介近年来,大规模语言模型(LLM)领域取得了令人瞩目的进展。语言模型的参数规模从早期的数百万(如ELMo、GPT-1),发展到如今的数十亿甚至上万亿(如GPT-3、PaLM和SwitchTransformers)。随着模型规模的增长,LLM的能力显著提升,展现出更接近人类的语言流畅性,并能执行多样化的自然语......
  • 内存函数详解
    1.memcpy使⽤和模拟实现2.memmove使⽤和模拟实现3.memset函数的使⽤4.memcmp函数的使⽤一.memcpy的使用与模拟实现1.定义:注意:1.memcpy返回的是目的地的指针      2.使用时要包含头文件string.h      3.num指的是拷贝的个数(单位为字节)2.......
  • PlantUML+vscode使用详解
    目录PlantUML使用1.Uml图1.1Uml类图1.2类图关系2.PlantUML功能概述2.1PlantUML核心特性2.2PlantUML的优势3.文本定义语言生成图表PlantUML学习指南4.自动转换c#源码工具4.1CSharptoPlantUML(VisualStudioCode扩展)4.2PlantUmlClassDiagramGeneratorNuget地址安装使用示......
  • 最全亚马逊批量实时采集商品链接方法(图文详解),还能看市场集中度!
    第一步:准备关键词、类目ID、店铺ID、ASIN可以通过选关键词、选类目2种方式采集关键词,自己卡条件批量下载下来。第二步:了解以词挖品、类目top1万采集、畅销榜采集、店铺挖品、僵尸链接、asin采集等等以词挖品方法一以词挖品方法二以词挖品方法三以词挖品方法四......
  • HarmonyOS Next加解密算法中的参数与模式详解
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)中加解密算法参数与模式的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。一、加解密参数......
  • 详解线程的三大特性:原子性、可见性和有序性
    在多线程编程中,理解线程的原子性、可见性和有序性是构建正确并发程序的基础。以下是它们的详细解释:1.原子性(Atomicity)定义原子性指的是操作不可被中断,要么全部执行完成,要么完全不执行。特性原子性操作在执行时不会被其他线程干扰。如果多个线程同时访问共享资......
  • 嵌入式硬件电子电路设计(七)稳压二极管-齐纳二极管-齐纳击穿全面详解
    引言:在嵌入式硬件电子电路设计中,稳压二极管(又称齐纳二极管)是一种常用的元件,主要用于电压稳定、过压保护和电路调试。齐纳二极管利用齐纳击穿效应,在反向工作状态下能够维持稳定的电压输出,因此被广泛应用于各种电源电路和信号调理电路中。理解齐纳二极管的工作原理及其在实际电路......