DMA(Direct Memory Access,直接内存访问)是一种计算机系统中的数据传输技术,它的作用是在不需要CPU干预的情况下,实现高速、高效的数据传输。
传统情况下,当需要进行数据传输时,CPU通常需要通过程序控制来完成数据的读取或写入操作。这种方式会消耗CPU的时间和资源,限制了系统的性能和效率。而DMA技术的引入,可以解放CPU,让它专注于更复杂的任务,同时实现高速的数据传输。
DMA的作用主要体现在以下几个方面:
1. 高速数据传输:DMA通过直接访问系统内存,绕过CPU,实现设备与内存之间的高速数据传输。它可以在设备和内存之间直接传输大块的数据,避免了CPU的频繁干预和数据拷贝,提高了数据传输的速度和效率。
2. 减轻CPU负担:DMA可以在数据传输过程中独立操作,不需要CPU的干预。这样可以减轻CPU的负担,使其能够更好地处理其他任务,提高系统的整体性能。
3. 多设备并行传输:DMA可以同时支持多个设备的数据传输,实现多设备的并行操作。这对于需要同时处理多个设备的系统来说,可以提高系统的吞吐量和响应速度。
4. 数据格式转换:DMA还可以实现数据格式的转换。例如,将设备传输的数据从一种格式转换为另一种格式,以适应不同设备之间的数据格式要求。
总之,DMA的作用是通过直接访问内存,实现高速、高效的数据传输,减轻CPU负担,提高系统性能,并支持多设备的并行操作和数据格式转换。它在许多领域的计算机系统中得到广泛应用,如网络通信、音视频处理、存储设备等。
DMA可以解决ADC通道信息覆盖的问题。
接线图:
main函数:
#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();
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);
}
}
#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);
//按图配置DMA1单元
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);
DMA_Cmd(DMA1_Channel1, DISABLE);
}
void MyDMA_Transfer(void)
{
//因为是正常模式,SIZE减为0后就会停止,若想再次转运必须DISABLE再ENABLE
DMA_Cmd(DMA1_Channel1, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);
DMA_Cmd(DMA1_Channel1, ENABLE);
while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
DMA_ClearFlag(DMA1_FLAG_TC1);
}