STM32特有的数据搬运方式--基于DMA外设的数据搬运

1.DMA 可以提供 外设寄存器(也是存储器的一种,只是可以用来读写,是软件和硬件的桥梁)和存储器 ,或者 存储器和存储器 之间的高速数据传输,无须 CPU 干预,节省了 CPU 的资源。
外设寄存器:一般指的是 DR 数据寄存器比如 ADC/ 串口的数据寄存器 存储器:运行内存 SRAM 和程序存储器 flash, 即存储变量数组和程序代码的地方。
2. STM32F103C8T6 DMA 资源: DMA1 7 个通道)每个通道都支持软件触发和特定的硬件
3.触发(每个 DMA 有特点的触发源)
软件触发:存储器转运到存储器(一次性转运完数据就结束)软件触发所有通道都可以使用
硬件触发: 外设的数据 转运到存储器(外设的数据有特定的时间节点的限制), 硬件触发要选择指定的 DMA 通道。

 

4.DMA的基本结构框图

DMA触发的条件:

  1. 传输计数器大于0
  2. 触发源有触发信号。若为软件触发,则一直都会有触发信号。
  3. DMA使能,使用DMACmd函数
  4. ps:若需要DMA搬运ADC的数据,则选择硬件触发源,还需开启ADC到DMA的硬件触发信号
5.使用DMA的步骤
DMA初始化函数:
第一步:开启DMA时钟:RCC_AHBPeriphClockCmd
第二步:使用结构体初始化DMA: 包括外设和存储器的起始地址,数据宽度,地址是否自增、传输方向、传输计数器(传输计数器是否需要自动重装)、选择触发源、通道优先级等
DMA转运执行函数(调用一次次函数就执行一次DMA转运):
第一步:先使得DMA使能
第二步:给传输计数器赋值
第三步:DMA使能
第四步:在while循环中使用DMA_GetITStatus获得DMA是否转运完成的标志位。
第五步:使用DMA_ClearFlag清除转运完成的标志位。
主函数:
第一步:调用DMA初始化函数
第二步:在while循环中调用DMA转运执行函数。
代码部分(使用DMA搬运数据---软件触发)
//模块一:DMA初始化函数+DMA执行转运函数

#include "stm32f10x.h"                  // Device header

uint16_t MyDMA_Size;//传输计数器的值,全局变量

/*初始化DMA:
RCC开启DMA时钟
外设和存储器的起始地址,数据宽度,地址是否自增
传输方向
传输计数器(传输计数器是否需要自动重装)
选择触发源
通道优先级
开关控制
若为硬件触发需要调用XXX_DMACmd,开启触发信号输出。
如果需要DMA的中断,就需要调用DMA_ITConfig开启中断输出,并在NVIC配置相应的中断通道。*/
void MyDMA_Init(uint32_t AddrA,uint32_t AddrB,uint16_t Size)//地址必须是32位的
{
	MyDMA_Size=Size;//把初始化的Size赋值给全局变量MyDMA_Size
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	
    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; //被转运起始地址
	DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;//存储器字节
	DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; //存储器地址是否自增

	DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC; //传输方向
	DMA_InitStructure.DMA_BufferSize=Size; //传输计数器的值,不同的传输数量传输的次数不同
	DMA_InitStructure.DMA_Mode=DMA_Mode_Normal; //数据传输的模式,即需不需要自动重装功能
	DMA_InitStructure.DMA_M2M=DMA_M2M_Enable; //触发方式,此处选择软件触发
	DMA_InitStructure.DMA_Priority=DMA_Priority_Medium; //配置优先级
		DMA_Init(DMA1_Channel1,&DMA_InitStructure); //DMA1,通道1,DMA初始化
	
    DMA_Cmd(DMA1_Channel1,DISABLE); //DMA失能,不让DMA初始化就开始转运,而放在DMA转运函数中
	
	/*DMA工作的条件:
	1.传输计数器大于0
	2.触发源有触发信号 若为软件触发,则一直都会有触发信号
	3.DMA使能。
	*/

}

//调用一次次函数就执行一次DMA转运
void MyDMA_Transfer(void)
{
//若想给传输计数器再次赋值,需要将DMA失能:DMA_Cmd(DMA1_Channel1,DISABLE)
DMA_Cmd(DMA1_Channel1, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel1,MyDMA_Size); //给传输计数器再次赋值
DMA_Cmd(DMA1_Channel1,ENABLE); //DMA使能
while (DMA_GetITStatus(DMA1_FLAG_TC1)==RESET);//若未转运完成,则一直等待转运完成
DMA_ClearFlag(DMA1_FLAG_TC1);
}

//主函数

#include "stm32f10x.h"                  // Device header
#include"Delay.h"
#include"OLED.h"
#include"MyDMA.h"

uint8_t DataA[]={0x01,0x02,0x03,0x04};
uint8_t DataB[]={0,0,0,0};

int main(void)
{
	//初始化OLED;
	OLED_Init();
	
	//调用此函数DateA数组的数据,立刻传输到DataB中
	MyDMA_Init((uint32_t)DataA,(uint32_t)DataB,4); 
	
	OLED_ShowString(1,1,"DataA");
	OLED_ShowString(3,1,"DataB");
	OLED_ShowHexNum(1,8,(uint32_t)DataA,8);
	OLED_ShowHexNum(3,8,(uint32_t)DataB,8);
	
	
	
	while(1)
 {
	DataA[0]++;
	DataA[1]++;
	DataA[2]++;
	DataA[3]++;

	OLED_ShowHexNum(2,1,DataA[0],2);
	OLED_ShowHexNum(2,4,DataA[1],2);
	OLED_ShowHexNum(2,7,DataA[2],2);
	OLED_ShowHexNum(2,10,DataA[3],2);
    OLED_ShowHexNum(4,1,DataB[0],2);
	OLED_ShowHexNum(4,4,DataB[1],2);
	OLED_ShowHexNum(4,7,DataB[2],2);
	OLED_ShowHexNum(4,10,DataB[3],2);
	Delay_ms(1000);
	 
    MyDMA_Transfer();
	
	OLED_ShowHexNum(2,1,DataA[0],2);
	OLED_ShowHexNum(2,4,DataA[1],2);
	OLED_ShowHexNum(2,7,DataA[2],2);
	OLED_ShowHexNum(2,10,DataA[3],2);
    OLED_ShowHexNum(4,1,DataB[0],2);
	OLED_ShowHexNum(4,4,DataB[1],2);
	OLED_ShowHexNum(4,7,DataB[2],2);
	OLED_ShowHexNum(4,10,DataB[3],2);
	Delay_ms(1000);
	
}
 }

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值