DMA是干嘛的?
- 学习一个东西我们首先要知道它是做什么的,那么DMA它是做什么的呢?DMA控制器是用来减轻CPU的负担,直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传 输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。说人话就是用来搬运的,比如数组之间的搬运,把一个数组里的数据通过DMA无需CPU干扰的情况下之间搬到另外一个数组里,大大的释放了CPU的压力,可以让CPU去干更多的事。
DMA的通道优先级是怎样的呢?
- STM32有两个DMA,分别是DMA1和DMA2,DMA1有7个通道,DMA2有5个通道,通道的优先级可以通过软件去设置,如果设置的优先级一样那么就是数值小的优先级高于数值大的优先级,如:DMA1的通道1>DMA1的通道2在设置相同的优先级情况下,DMA1的通道1>DMA2的通道1。
DMA的模式
-
正常模式
一次DMA数据传输完后,停止DMA传送,也就是只传输一次。要开始新的DMA传输,需要在关闭DMA通道的情况下,在DMA CNDTRx寄存器中重新写入传输数目。
循环传输模式
当传输结束时,硬件自动会将传输数据量寄存器进行重装,进行下一轮的数据传输。 也就是多次传输模式。主要用于处理循环缓冲区和连续的数据传输。
DMA增量模式
外设和存储器指针在每次传输后可以自动向后递增或保持常量。当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量值。就是相当于数组的遍历,让数组当中每一个值都会穿到另外一个数组去。如:第一次是数组[0]第二次就是数组[1]~~~~第n次就是数组[n]。
DMA数组搬运实验
//内设地址
uint32_t arr[size]={0x123,0x456,0xab,0x485};
//外设地址
uint32_t arr1[size];
//DMA初始化
void DMA_init()
{
//打开时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
DMA_InitTypeDef DMA_struct;
//用来设置传输数据大小
DMA_struct.DMA_BufferSize=32;
//设置外设作为传输目的地
DMA_struct.DMA_DIR=DMA_DIR_PeripheralDST;
//运行内存之间的传输
DMA_struct.DMA_M2M=DMA_M2M_Enable;
//内设地址
DMA_struct.DMA_MemoryBaseAddr=(uint32_t)arr;
//内设字长
DMA_struct.DMA_MemoryDataSize=DMA_MemoryDataSize_Word;
//增量模式
DMA_struct.DMA_MemoryInc=DMA_MemoryInc_Enable;
//正常模式
DMA_struct.DMA_Mode=DMA_Mode_Normal;
//外设地址
DMA_struct.DMA_PeripheralBaseAddr=(uint32_t)arr1;
//外设字长
DMA_struct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Word;
//外设自增模式
DMA_struct.DMA_PeripheralInc=DMA_PeripheralInc_Enable;
//优先级
DMA_struct.DMA_Priority=DMA_Priority_High;
DMA_Init(DMA1_Channel1,&DMA_struct);
DMA_Cmd(DMA1_Channel1,ENABLE);
}
//用来看数组搬运是否成功
uint16_t dma_pass(uint32_t *arr,uint32_t *arr1,uint32_t buff)
{
int i=0;
for(i=0;i<buff;i++)
{
if(arr[i]==arr1[i])
{
return 1;//成功
}else{
return 0;//失败
}
}
}