学习笔记--DMA

一、原理

        DMA(Direct Memory Access)直接存储器存取。可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源。多个独立可配置的通道,每个通道都支持软件触发和特定的硬件触发。

1、DMA框图

         (1)DMA总线:连接在DMA和总线矩阵之间,用于访问各个存储器。

        (2)DMA通道:DMA内部多个通道,可以独立的数据转运,但每次只有一个一个通道可以使用DMA。

        (3)仲裁器:用于调度各个通道,防止发生冲突。

        (4)AHB从设备:用于配置DMA参数

        (5)DMA请求:连接DMA与外设之间,用于硬件触发DMA的数据转运

2、DMA基本结构图

         其中,由M2M给1/0来确定是软件触发/硬件触发。软件触发通常用于存储器与存储器中间的数据转运,硬件触发常用于外设与存储器之间的数据转运。

        传输计数器内部的值是DMA转运的次数,在DMA每转运一次就自动减一,直到为0时,DMA停止。DMA转运可以设置自动重装器在传输计数器为0时再装入新值,这样DMA就会不停的传输,这是DMA的连续模式。如果没有设置自动重装器,要手动改写时,一定要先关闭开关控制,然后去改写传输计数器的值,再打开开关才可以。

3、DMA内部框图

4、DMA数据宽度与对其

         第一列是源端宽度、第二列是目标宽度、第三列是传输数目、第四列是源段的地址/数据、第五列是传输操作、第六列是目标的地址/数据。

        当源端数据宽度 > 目标宽度时,只有低位传入,高位被砍掉。

        当源端数据宽度 < 目标宽度时,数据全部传入,高位补0。

二、代码实现

1、参数配置

         先开了个定时器,让他100ms更新一次ADC转换事件

         然后配置ADC转换,配置3个通道并使能扫描模式,使能DMA功能,由定时器3触发。

         最后配置3个DMA。他们三个分3个通道。其中接收配置为循环模式,发送和ADC是普通模式。

2、程序设计

        在main函数里定义一个接收ADC采样数据的的数组和接收数组。

        分别打开ADC的DMA转换、定时器、串口接收DMA功能。

        回调函数.c如下

#include "funtion.h"

uint8_t u_buf[256];
#define printF(...) HAL_UART_Transmit_DMA(&hlpuart1,(uint8_t *)u_buf,sprintf((char*)u_buf,__VA_ARGS__))

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
	for(int i = 0;i < 27;)
	{
		ad1 += adc_value[i++];
		ad2 += adc_value[i++];
		ad3 += adc_value[i++];
	}
	ad1 /= 10;
	ad2 /= 10;
	ad3 /= 10;

	HAL_ADC_Stop(&hadc1);
	HAL_ADC_Start_DMA(&hadc1, adc_value, 30);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart == &hlpuart1)
	{
		if(Rx_Data[0] == '0')
		{
			printF("---------------ADC DMA Example---------------\r\n");
		}
		else if(Rx_Data[0] == '1')
		{
			printF("AD1 value = %1.3fV\r\n", ad1*FACTOR_ADC);
		}
		else if(Rx_Data[0] == '2')
		{
			printF("AD2 value = %1.3fV\r\n", ad2*FACTOR_ADC);
		}
		else if(Rx_Data[0] == '3')
		{
			printF("AD3 value = %1.3fV\r\n", ad3*FACTOR_ADC);
		}
	}

}

void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart == &hlpuart1)
	{
		HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
	}
}

        回调函数.h如下

#include "main.h"
#include "adc.h"
#include "usart.h"
#include "stdio.h"

#define FACTOR_ADC 0.00080586
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

uint32_t adc_value[30];
uint32_t ad1=0, ad2=0, ad3=0;

extern unsigned char Rx_Data[2];

PUTCHAR_PROTOTYPE
{
//	HAL_UART_Transmit(&hlpuart1 , (uint8_t *)&ch, 1, 0xffff);
	HAL_UART_Transmit_DMA(&hlpuart1 , (uint8_t *)&ch, sizeof(&ch));
	return ch;
}

三、任务结果

PCIE-DMA是一种基于PCIe接口的直接内存访问技术,能够实现高速数据传输。在我的学习笔记中,我详细记录了与PCIE-DMA相关的知识和学习心得。 首先,我了解到PCIE-DMA技术的基本原理和作用。PCIE-DMA可以通过PCIe总线直接访问系统内存中的数据,而不需要过多的CPU干预,提高数据传输的速度和效率。这种技术在需要大量数据传输的场景下非常有效,比如高性能计算、数据采集等。 其次,我深入学习了PCIE-DMA的工作原理。PCIE-DMA的核心是DMA控制器,它负责管理和控制数据传输的流程。当设备需要读写内存中的数据时,它通过DMA控制器发送请求,然后DMA控制器生成一个事务,将数据直接传输到或从内存中。这样就大大减少了CPU的参与,提高了数据传输的效率。 另外,我还学习了PCIE-DMA配置和编程方法。PCIE-DMA配置主要包括硬件配置和软件配置两个部分。硬件配置通常涉及到DMA控制器和PCIe接口的初始化配置,软件配置则需要编写驱动程序来驱动DMA控制器和处理数据传输过程中的事件和异常。这部分内容对于我来说还比较新颖,需要更多的实践和实践。 最后,我总结了PCIE-DMA的应用场景和发展前景。PCIE-DMA在高性能计算、数据采集等领域具有广阔的应用前景。随着数据量的不断增加和传输速度的要求越来越高,PCIE-DMA技术的需求也将越来越大。因此,对于我来说,学习掌握PCIE-DMA技术非常有价值。 通过学习和记录PCIE-DMA的相关知识和经验,我对这项技术有了更深入的理解和掌握。希望将来能通过应用PCIE-DMA技术解决实际问题,为科研和工程项目的顺利进行做出贡献。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值