您的位置 首页 FPGA

stm32中DMA根本运用

DMA有什么用?直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地…

DMA有什么用?

直接存储器存取用来供给在外设和存储器之间或许存储器和存储器之间的高速数据传输。无须CPU的干涉,经过DMA数据能够快速地移动。这就节省了CPU的资源来做其他操作。

有多少个DMA资源?

有两个DMA操控器,DMA1有7个通道,DMA2有5个通道。

数据从什么地方送到什么地方?

外设到SRAM(I2C/UART等获取数据并送入SRAM);

SRAM的两个区域之间;

外设到外设(ADC读取数据后送到TIM1操控其发生不同的PWM占空比);

SRAM到外设(SRAM中预先保存的数据送入DAC发生各种波形);

……还有一些现在还搞不清楚的。

DMA能够传递多少数据?

传统的DMA的概念是用于大批量数据的传输,可是我了解,在STM32中,它的概念被扩展了,惹祸更多的时分快速是其运用的要点。数据能够从1~65535个。

直接存储器存取(Direct Memory Access,DMA)是计算机科学中的一种内存拜访技能。它答应某些电脑内部的硬体子体系(电脑外设),能够独立地直接读写体系存储器,而不需绕道 CPU。在平等程度的CPU担负下,DMA是一种快速的数据传送方法。它答应不同速度的硬件设备来交流,而不需求依于 CPU的很多中止恳求。

现在越来越多的单片机选用DMA技能,供给外设和存储器之间或许存储器之间的高速数据传输。当 CPU 初始化这个传输动作,传输动作自身是由DMA 操控器来实施和完结。STM32就有一个DMA操控器,它有7个通道,每个通道专门用来办理一个或多个外设对存储器拜访的恳求,还有一个裁定器来和谐各个DMA恳求的优先权。

DMA 操控器和Cortex-M3核同享体系数据总线碑文直接存储器数据传输。当CPU和DMA一起拜访相同的方针(RAM或外设)时,DMA恳求可能会中止 CPU拜访体系总线达若干个周期,总线裁定器碑文循环调度,以确保CPU至少能够得到一半的体系总线(存储器或外设)带宽。

在发生一个事情后,外设发送一个恳求信号到DMA操控器。DMA操控器依据通道的优先权处理恳求。当DMA操控器开端拜访外设的时分,DMA操控器当即发送给外设一个应对信号。当从DMA操控器得到应对信号时,外设当即开释它的恳求。一旦外设开释了这个恳求,DMA操控器一起吊销应对信号。假如发生更多的恳求时,外设能够发动下次处理。

总归,每个DMA传送由3个操作组成:

1. 从外设数据寄存器或许从DMA_CMARx寄存器指定地址的存储器单元碑文加载操作。

2. 存数据到外设数据寄存器或许存数据到DMA_CMARx寄存器指定地址的存储器单元。

3. 碑文一次DMA_CNDTRx寄存器的递减操作。该寄存器包括未完结的操作数目。

裁定器依据通道恳求的优先级来发动外设/存储器的拜访。优先级分为两个等级:软件(4个等级:最高、高、中等、低)、硬件(有较低编号的通道比具有较高编号的通道有较高的优先权)。

能够在DMA传输过半、传输完结和传输错误时发生中止。

STM32中DMA的不同中止(传输完结、半传输、传输完结)经过“线或”方法衔接至NV%&&&&&%,需求在中止例程中进行判别。

进行DMA装备前,不要忘了在RCC设置中使能DMA时钟。STM32的DMA操控器挂在AHB总线上。

DMA总共有7个通道,各个通道的DMA映射联络如下:

外设的事情衔接至相应DMA通道,每个通道均能够经过软件触发完结存储器内部的DMA数据传输(M2M形式)

Tips:库2.0中函数RCC_AHBPeriphClockCmd的参数由“RCC_AHBPeriph_DMA”改成“RCC_AHBPeriph_DMA1”(假如是DMA1操控器的话)。

DMA的传输标志位(CHTIFx、CTCIFx、CGIFx)由硬件设置为“1”,但需求软件清零,在中止服务程序中铲除。当CGIFx(大局中止标志位)清零后,CHTIFx 和 CTCIFx均清零。

进程:怎样启用DMA?首要,众所周知的是初始化,任何设备启用前都要对其进行初始化,要对模块初始化,还要先了解该模块相应的结构及其函数,以便正确的设置;我们DMA较为杂乱,我就只谈谈DMA的根本结构和和常用函数,这些都是ST公司供给在库函数中的。

1、 下面代码是一个规范DMA设置,当然实践运用中可依据实践情况进行削减:

DMA_DeInit(DMA_Channel1);

上面这句是给DMA装备通道,依据ST供给的材料,STM3210Fx中DMA包括7个通道(CH1~CH7),也便是说能够为外设或memory供给7座“桥梁”(请答应我运用桥梁一词,我觉得更简单了解,,别“拍砖”呀!);

DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

上面语句中的DMA_InitStructure是一个DMA结构体,在库中有声明晰,当然运用时就要先界说了;DMA_PeripheralBaseAddr是该结构体中一个数据成员,给DMA一个开端地址,好比是一个buffer开端地址,数据流程是:外设寄存器à DMA_PeripheralBaseAddàmemory中变量空间(或flash中数据空间等),ADC1_DR_Address是我界说的一个地址变量;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue;

上面这句很显然是DMA要衔接在Memory中变量的地址,ADC_ConvertedValue是我自己在memory中界说的一个变量;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

上面的这句是设置DMA的传输方向,就如前面我所说的,DMA能够双向传输,也能够单向传输,这儿设置的是单向传输,假如需求双向传输:把DMA_DIR_PeripheralSRC改成DMA_DIR_PeripheralDST即可。

DMA_InitStructure.DMA_BufferSize = 2;

上面的这句是设置DMA在传输时缓冲区的长度,前面有界说过了buffer的开端地址:ADC1_DR_Address ,为了安全性和可靠性,一般需求给buffer界说一个贮存片区,这个参数的单位有三种类型:Byte、HalfWord、word,我设置的2个half-word(见下面的设置);32位的MCU中1个half-word占16 bits。

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

上面的这句是设置DMA的外设递加形式,假如DMA选用的通道(CHx)有多个外设衔接,需求运用外设递加形式:DMA_PeripheralInc_Enable;我的比如里DMA只与ADC1建立了联络,所以选用DMA_PeripheralInc_Disable

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

上面的这句是设置DMA的内存递加形式,DMA拜访多个内存参数时,需求运用DMA_MemoryInc_Enable,当DMA只拜访一个内存参数时,可设置成:DMA_MemoryInc_Disable。

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

上面的这句是设置DMA在拜访时每次操作的数据长度。有三种数据长度类型,前面现已讲过了,这儿不在叙说。

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

与上面相同。在此不再阐明。

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

上面的这句是设置DMA的传输形式:接二连三的循环形式,若只想拜访一次后就不要拜访了(或按指令操作来反诘,也便是想要它拜访的时分就拜访,不要它拜访的时分就中止),能够设置成通用形式:DMA_Mode_Normal

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

上面的这句是设置DMA的优先等级:能够分为4级:VeryHigh,High,Medium,Low.

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

上面的这句是设置DMA的2个memory中的变量相互拜访的

DMA_Init(DMA_Channel1,&DMA_InitStructure);

前面那些都是对DMA结构体成员的设置,在次再共同对DMA整个模块做一次初始化,使得DMA各成员与上面的参数共同。

/*DMA Enable*/

DMA_Cmd(DMA_Channel1,ENABLE);

stm32运用DMA的相关操作:
1、DMA的装备
要装备的有DMA传输通道挑选,传输的成员和方向、一般形式仍是循环形式等等。
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
//DMA设置:
//设置DMA源:内存地址&串口数据寄存器地址
//方向:内存–>外设
//每次传输位:8bit
//传输巨细DMA_BufferSize=SENDBUFF_SIZE
//地址自增形式:外设地址不增,内存地址自增1
//DMA形式:一次传输,非循环
//优先级:中
DMA_DeInit(DMA1_Channel4);//串口1的DMA传输通道是通道4
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;
DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralDST;//外设作为DMA的意图端
DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;//传输巨细
DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable;//外设地址不添加
DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable;//内存地址自增1
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode =DMA_Mode_Circular;
//DMA_Mode_Normal(只传送一次),DMA_Mode_Circular (不停地传送)
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//(DMA传送优先级为中等)
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
}
注:
1、传输通道:经过查表,串口1的发送对应的是DMA的通道4,所以此处挑选通道4.
2、DMA传输方法:
(1) DMA_Mode_Normal,正常形式,当一次DMA数据传输完后,中止DMA传送,关于上例而言,便是DMA_PeripheralDataSize_Byte个字节的传送完结后,就中止传送。
(2)DMA_Mode_Circular
循环形式,当传输完一次后,从头接着传送,永不暂停。
2、外设的DMA方法设置
将串口1设置成DMA形式:
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
3、待传输数据的界说和初始化
#define SENDBUFF_SIZE 10240
vu8 SendBuff[SENDBUFF_SIZE];
for(i=0;i {
SendBuff[i] = i%10+0;
}
4、开端DMA传输(使能对应的DMA通道)
DMA_Cmd(DMA1_Channel4, ENABLE);
5、DMA传输的完结
while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET)
{
LED_1_REV; //LED翻转
Delay(); //浪费时间
}
当传输完结后,就会跳出上面的死循环。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/fpga/265294.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部