DMA转运数据学习

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

文章目录

前言

一、DMA

二、使用步骤

1.DMA的初始化配置(DMA.C)

2.多次转运函数(DMA.C)

3.主函数调用(main.c)

总结


前言

DMA数据转运学习


提示:以下是本篇文章正文内容,下面案例可供参考

一、DMA

DMA,全称Direct Memory Access,即直接存储器访问。

DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。

二、使用步骤

1.DMA的初始化配置(DMA.C)

代码如下(实例STM32F103):

#include "stm32f10x.h"                  // Device header

uint16_t MyDMA_Size;                    //定义全局变量;用于取值

void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)                            //DMA初始化;参数设置三个;AddrA为外设地址;AddrB为存储器地址;Size为传输几次
{
    MyDMA_Size = Size;                    //赋值;取值
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                                    //开启DMA1的时钟;注意:这里是AHB总线
    
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;                                    //设置外设地址AddrA
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;                //设置数据宽度;DMA_PeripheralDataSize_Byte字节宽度
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;                        //设置是否自增;DMA_PeripheralInc_Enable:自增;DMA_PeripheralInc_Disable:不自增
    DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;                                        //设置存储器地址AddrB
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                        //设置数据宽度;Size字节宽度
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                //设置是否自增;Enable:自增;Disable:不自增
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                    //设置方向;DMA_DIR_PeripheralSRC:外设站点到存储器站点;DMA_DIR_PeripheralDST:存储器站点到外设站点;
    DMA_InitStructure.DMA_BufferSize = Size;                                            //设置传输计数器的次数
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                        //设置模式(是否自动重装);Normal正常递减到零停止(不重装);DMA_Mode_Circular:循环模式(自动重装)
    DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;                                            //设置触发源(M2M:软件到软件);DMA_M2M_Enable:软件触发;DMA_M2M_Disable:硬件触发;
                                                                                        //注意:自动重装和软件出发不能同时使用,会造成死循环
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                                //设置优先级:DMA_Priority_Medium中等优先级;如果多个DMA可以设置一下以便取值
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    
    DMA_Cmd(DMA1_Channel1, DISABLE);                                                    //使能开启DMA1的通道1
}

2.多次转运函数(DMA.C)

代码如下(示例):

void MyDMA_Transfer(void)                                                                //传输DMA;调用这个函数就再次启动一次DMA的转运
{
    DMA_Cmd(DMA1_Channel1, DISABLE);                                                    //失能关闭DMA1的通道1
    DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);                                    //设置当前数据寄存器的值(用来传输计数器写数据)DMA1_Channel1(DMA1的通道1)MyDMA_Size(获取的值)
    DMA_Cmd(DMA1_Channel1, ENABLE);                                                        //使能开启DMA1的通道1
    
    while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);                                    //获取标志位状态;DMA1_FLAG_TC1(通道 1 传输完成标志位)
    DMA_ClearFlag(DMA1_FLAG_TC1);                                                        //清楚标志位
}

3.主函数调用(main.c)

#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_Init();											//OLED初始化
	
	MyDMA_Init((uint32_t)DataA, (uint32_t)DataB, 4);		//调用初始化MDA(A的地址,B的地址,想要传输数据的个数也就是传输几次)
	
	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] ++;										//数据A 自增
		DataA[1] ++;
		DataA[2] ++;
		DataA[3] ++;
		
		OLED_ShowHexNum(2, 1, DataA[0], 2);					//显示A地址数据
		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);					//显示B地址数据 
		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();									//调用自动转运DMA数据函数
		
		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、付费专栏及课程。

余额充值