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();
}
}
Comments NOTHING