DMA

singlemouse 发布于 2023-08-11 1189 次阅读


Table of Contents

DMA笔记

DMA简介

•DMA(Direct Memory Access)直接存储器存取

•DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源

•12个独立可配置的通道: DMA1(7个通道), DMA2(5个通道)

•每个通道都支持软件触发和特定的硬件触发

•STM32F103C8T6 DMA资源:DMA1(7个通道)

存储器映像

DMA框图

简单了解即可


DMA基本结构

打通步骤

一、RCC开启DMA时钟

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

二、初始化DMA

    DMA_InitTypeDef DMA_InitStruct;
    DMA_InitStruct.DMA_PeripheralBaseAddr = AddrA; // 外设站点的起始地址(AddrA是传入的)
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设站点的数据宽度(以字节方式传输)
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Enable; // 外设站点是否自增
    DMA_InitStruct.DMA_MemoryBaseAddr = AddrB; // 存储器站点的起始地址(AddrB也是传入的)
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 存储器站点的数据宽度(以字节方式传输)
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable ; // 存储器站点是否自增
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; // 传输方向(外设站点到储存器站点)
    DMA_InitStruct.DMA_BufferSize = Size; // 传输次数(Size也是传入的)
    DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; // 是否启用自动重装(选择转运一次就停下来)
    DMA_InitStruct.DMA_M2M = DMA_M2M_Enable; // 选择硬件触发或软件触发
    DMA_InitStruct.DMA_Priority = DMA_Priority_Medium; // 优先级(单通道选择随意)
    DMA_Init(DMA1_Channel1,&DMA_InitStruct);

三、控制开关

    DMA_Cmd(DMA1_Channel1,ENABLE);

部分API

void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx); // 恢复缺省配置
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct); // 初始化
void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct); // 结构体初始化
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState); //使能
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState); // 中断输出使能
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); // 设置当前数据寄存器
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx); // 获取当前数据寄存器
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG); // 获取标志位状态
void DMA_ClearFlag(uint32_t DMAy_FLAG); // 清除标志位
ITStatus DMA_GetITStatus(uint32_t DMAy_IT); // 获取中断状态
void DMA_ClearITPendingBit(uint32_t DMAy_IT); // 清除中断挂起位

DMA请求

简单了解即可

数据宽度与对齐

简单了解即可

数据转运+DMA

ADC扫描模式+DMA

实验部分

使用DMA转运数组数据

DMA模块
#include "stm32f10x.h"                  // Device header

uint16_t MyDMA_Size;

void MyDMA_Init(uint32_t AddrA,uint32_t AddrB, uint16_t Size)
{
    MyDMA_Size = Size;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    DMA_InitTypeDef DMA_InitStruct;
    DMA_InitStruct.DMA_PeripheralBaseAddr = AddrA; // 外设站点的起始地址(AddrA是传入的)
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设站点的数据宽度(以字节方式传输)
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Enable; // 外设站点是否自增
    DMA_InitStruct.DMA_MemoryBaseAddr = AddrB; // 存储器站点的起始地址(AddrB也是传入的)
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 存储器站点的数据宽度(以字节方式传输)
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable ; // 存储器站点是否自增
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; // 传输方向(外设站点到储存器站点)
    DMA_InitStruct.DMA_BufferSize = Size; // 传输次数(Size也是传入的)
    DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; // 是否启用自动重装(选择转运一次就停下来)
    DMA_InitStruct.DMA_M2M = DMA_M2M_Enable; // 选择硬件触发或软件触发
    DMA_InitStruct.DMA_Priority = DMA_Priority_Medium; // 优先级(单通道选择随意)
    DMA_Init(DMA1_Channel1,&DMA_InitStruct);

    DMA_Cmd(DMA1_Channel1,ENABLE);

}

void MyDMA_Transfer(void) // 每调用一次函数,则再次启动一次DMA转运
{
    DMA_Cmd(DMA1_Channel1,DISABLE); // 先关闭DMA
    DMA_SetCurrDataCounter(DMA1_Channel1,MyDMA_Size); // 直接获取初始化函数中传入的值
    DMA_Cmd(DMA1_Channel1,ENABLE); // 再开启DMA

    while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET); // 等待转运完成(转运完成标志位)
    DMA_ClearFlag(DMA1_FLAG_TC1); // 清除标志位
}
主函数
#include "stm32f10x.h"                  // Device header
#include "MyDMA.h"

int main(void)
{
    uint8_t DataA[] = {0x01,0x02,0x03,0x04}; // 起始数组
    uint8_t DataB[] = {0,0,0,0}; // 目的数组
    MyDMA_Init((uint32_t)DataA,(uint32_t)DataB,4); // 起始数组、目的数组、传输次数

    while (1)
    {
        DataA[0] ++;
        DataA[1] ++;
        DataA[2] ++;
        DataA[3] ++;
        MyDMA_Transfer();
    }
}
此作者没有提供个人介绍
最后更新于 2023-08-27