DMA数据转运
第一步,RCC开启DMA的时钟
第一步,直接调用DMA_Init,初始化这里各个参数,包括外设和存储器站点的起始地址,数据宽度,地址是否自增、方向、传输计数器、是否需要自动重装,选择触发源、通道优先级,那这所有的参数,通过一个结构体,就可以配置好了。
第三步,就可以进行开关控制,DMA_Cmd,给指定的通道使能,就完成了。
那在这里,如果你选择的是硬件触发不要忘了在对应的外设调用一下XXX_DMACmd,开启一下触发信号的输出;如果你需要DMA的中断,那就调用DMA_ITConfig,开启中断输出,再在NVIC里,配置相应的中断通道,然后写中断函数就行了。
第四步,在运行的过程中,如果转运完成,传输计数器清0了。这时想再给传输计数器赋值的话,就DMA失能、写传输计数器、DMA使能,这样就行了。
DMA库函数
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);//清除中断挂起位
初始化第一步,RCC开启DMA的时钟
注意:这里开启DMA时钟的时候,根据型号不同开启时钟参数也不同
这里说的是,对于互联型设备,这个参数可以是上面这些值的组合。互联型是STM32F105/107的型号。
对于其他设备,这个参数是上面的组合,我们是STM32F103所以选这个列表参数。
字节,uint8_t
半字,uint16_t
字,uint32_t
第一个是外设站点为DST,目的地,传输方向是:存储器站点到外设站点
第二个是外设站点为SRC,源端,传输方向是: 外设站点到存储器站点
打算把DataA放在外设站点,把DataB放在存储器站点,传输方向是: 外设站点到存储器站点
第一个是循环模式,就是传输计数器自动重装。
第二个是正常模式,就是传输计数器不自动重装,自减到0后停下来。
这里我们转运数组是,存储器到存储器的传输,所以选正常模式。
MyDMA.c
#include "stm32f10x.h" // Device header
uint16_t MyDMA_Size; //定义全局变量,用于Init函数的Size,供Transfer函数使用
/**
*函数:DMA初始化
*参数:AddrA 源数组的首地址
*参数:AddrB 目的数组的首地址
*参数:size转运的数据大小
*/
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size) //对于SRAM的数组,它的地址是编译器分配的,并不是固定的,是通过数组名来获取地址,这里把这个地址提取成初始化函数的参数。这样在初始化的时候,你相转运那个数组,就把哪个数组的地址传进来就行。
{
MyDMA_Size = Size; //初始化时,把size往全局变量也存一份
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启时钟,DMA是AHB总线的设备
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA; //外设站点的起始地址
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设站点的数据宽度。 以字节的方式传输
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; //外设站点的地址是否自增 。 地址自增
DMA_InitStructure.DMA_MemoryBaseAddr = AddrB; //存储器站点的起始地址。 给定形参AddrB
DMA_InitStructure.DMA