STM32的DMA


泉水

DMA介绍

DMA(Direct Memory Access) :直接存储器存取,是单片机的一个外设

  • 主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候, CPU 可以干其他的事情,好像是多线程一样。
    • 数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。
    • DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。

F407的DMA有多少数据流与通道?

F407开发指南28.1,P365。
STM32F4 最多有 2 个 DMA 控制器(DMA1 和 DMA2),共 16 个数据流(每个控制器 8 个),每一个 DMA 控制器都用于管理一个或多个外设的存储器访问请求。

  • 每个数据流通道都有一个仲裁器,用于处理 DMA 请求间的优先级。

F407的DMA如何判定DMA请求的优先级?

F407开发指南28.1,P365。

DMA框图

在这里插入图片描述

  • 注意上图中八个通道一个流,与上文所述一致。

F407的DMA源和目的的可选项?

F407开发指南,28.1,P366
这里特别注意一下,存储器到存储器需要外设接口可以访问存储器,而仅 DMA2 的外设接口可以访问存储器,所以仅 DMA2 控制器支持存储器到存储器的传输,DMA1 不支持。

F407DMA的主要特性

F407开发指南,28.1,P365

源与目的的方向配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

DMA必要性

定义一个变量
在这里插入图片描述其中a存储在了全局变量区域,但是在RAM中。
在这里插入图片描述第二行是将内存数据转移到串口的数据寄存器中。
在这里插入图片描述当串口的数据寄存器接收到数据之后就会由串口外设自动发送出去
在这里插入图片描述将数据从内存转移到外设寄存器中也是有CPU操作的。
一次转移大概需要1ms。如果是1万个,就需要10S。
对于单片机来说,10S种太长了。
因此,出现了DMA。

仲裁器

结合F407开发指南,28.1,P365讲仲裁器的部分
在这里插入图片描述
在这里插入图片描述

F407每个数据流对应请求映射

F407开发指南,28.1,P367
在这里插入图片描述
一对多的关系
DMA_SxCR 控制数据流到底使用哪一个通道,每个数据流有 8 个通道可供选择,每次只能选择其中一个通道进行 DMA 传输。

DMA结构

要注意的是 DMA2 只存在于大容量的单片机中。
DMA 控制器独立于内核,属于一个单独的外设,结构比较简单
在这里插入图片描述

STEM32的DMA 有 DMA1 和 DMA2 两个控制器, DMA1 有 7 个通道, DMA2 有 5 个通道,不同的 DMA 控制器的通道对应着不同的外设请求
在这里插入图片描述
在这里插入图片描述
其中 ADC3、 SDIO 和 TIM8 的 DMA 请求只在大容量产品中存在

DMA相关寄存器

DMA 中断状态寄存器(DMA_ISR)

在这里插入图片描述

如果开启了 DMA_ISR 中这些中断,在达到条件后就会跳到中断服务函数里面去,即使没开启,我们也可以通过查询这些位来获得当前 DMA 传输的状态。
常用的是 TCIFx,即通道 DMA 传输完成与否的标志。

DMA 中断标志清除寄存器(DMA_IFCR)

在这里插入图片描述

DMA_IFCR 的各位就是用来清除 DMA_ISR 的对应位的,通过写 0 清除。因为DMA_ISR寄存器为只读寄存器,所以在这些位被置位之后,只能这样来清除。

DMA 通道 x 配置寄存器(DMA_CCRx)

该寄存器有1-7个
该寄存器控制着 DMA 的很多相关信息,包括数据宽度、外设及存储器的宽度、通道优先级、增量模式、传输方向、中断允许、使能等都是通过该寄存器来设置的。所以 DMA_CCRx 是 DMA 传输的核心控制寄存器。

DMA 通道 x 传输数据量寄存器(DMA_CNDTRx)

这个寄存器控制 DMA 通道 x 的每次传输所要传输的数据量。其设置范围为 0~65535。并且该寄存器的值会随着传输的进行而减少,当该寄存器的值为 0 的时候就代表此次数据传输已经全部发送完成了。
所以可以通过这个寄存器的值来知道当前 DMA 传输的进度。

DMA 通道 x 的外设地址寄存器(DMA_CPARx)

该寄存器用来存储 STM32 外设的地址,比如我们使用串口 1,那么该寄存器必须写入 0x40013804(其实就是&USART1_DR)。如果使用其他外设,就修改成相应外设的地址就行了。

DMA 通道 x 的存储器地址寄存器(DMA_CMARx)

该寄存器和 DMA_CPARx 差不多,但是用来放存储器的地址的。
比如我们使用 SendBuf[5200]数组来做存储器,那么我们在DMA_CMARx 中写入&SendBuff 就可以了。

DMA通道配置步骤

DMA传输原理

  • 如果外设要想通过 DMA 来传输数据,必须先给 DMA 控制器发送 DMA 请求,从外设(TIMx、ADC、SPIx、I2Cx 和 USARTx)产生的 DMA 请求,通过逻辑或输入到DMA 控制器,这就意味着同时只能有一个请求有效。
  • DMA 收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且 DMA 控制器收到应答信号之后,就会启动 DMA 的传输,直到传输完毕。
  • 通道 1 的几个 DMA1 请求(ADC1、TIM2_CH3、TIM4_CH1),这几个是通过逻辑或到通道 1 的,这样我们在同一时间,就只能使用其中的一个。

我们要使用的是串口 1 的 DMA 传送,也就是要用到通道 4。

void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u16 ndtr)
{ 
 
	DMA_InitTypeDef  DMA_InitStructure;
	
	if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
	{
	  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
		
	}else 
	{
	  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能 
	}
  DMA_DeInit(DMA_Streamx);
	
	while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置 
	
  /* 配置 DMA Stream */
  DMA_InitStructure.DMA_Channel = chx;  //通道选择
  DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA外设地址
  DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器0地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
  DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量 
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
  DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化DMA Stream
	

} 
//开启一次DMA传输
//DMA_Streamx:DMA数据流,DMA1_Stream0~7/DMA2_Stream0~7 
//ndtr:数据传输量  
void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr)
{
 
	DMA_Cmd(DMA_Streamx, DISABLE);                      //关闭DMA传输 
	
	while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}	//确保DMA可以被设置  
		
	DMA_SetCurrDataCounter(DMA_Streamx,ndtr);          //数据传输量  
 
	DMA_Cmd(DMA_Streamx, ENABLE);                      //开启DMA传输 
}	  

 

F407 使能DMA 时钟

	if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
	{  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
	}else 
	{RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能 
	}



DMA_Stream_TypeDef *DMA_Streamx
可选项:

#define DMA1                ((DMA_TypeDef *) DMA1_BASE)
#define DMA1_Stream0        ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE)
#define DMA1_Stream1        ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE)
#define DMA1_Stream2        ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE)
#define DMA1_Stream3        ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE)
#define DMA1_Stream4        ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE)
#define DMA1_Stream5        ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE)
#define DMA1_Stream6        ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE)
#define DMA1_Stream7        ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE)
#define DMA2                ((DMA_TypeDef *) DMA2_BASE)
#define DMA2_Stream0        ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE)
#define DMA2_Stream1        ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE)
#define DMA2_Stream2        ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE)
#define DMA2_Stream3        ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE)
#define DMA2_Stream4        ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE)
#define DMA2_Stream5        ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE)
#define DMA2_Stream6        ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE)
#define DMA2_Stream7        ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE)

DAM复位

DMA_DeInit(DMA_Streamx);
可选项同上。

F407 DMA通道参数

void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx,DMA_InitTypeDef* DMA_InitStruct)

函数的第一个参数是指定初始化的 DMA 通道号
第二个参数是通过初始化结构体成员变量值来达到初始化的目的

typedef struct
{
uint32_t DMA_Channel;
uint32_t DMA_PeripheralBaseAddr;
uint32_t DMA_Memory0BaseAddr;
uint32_t DMA_DIR;
uint32_t DMA_BufferSize;
uint32_t DMA_PeripheralInc;
uint32_t DMA_MemoryInc;
uint32_t DMA_PeripheralDataSize;
uint32_t DMA_MemoryDataSize;
uint32_t DMA_Mode;
uint32_t DMA_Priority;
uint32_t DMA_FIFOMode;
uint32_t DMA_FIFOThreshold;
uint32_t DMA_MemoryBurst;
uint32_t DMA_PeripheralBurst;
}DMA_InitTypeDef;

DMA_Channel

用来设置 DMA 数据流对应的通道。

  • 可供每个数据流选择的通道请求多达 8 个,取值范围为:DMA_Channel_0~ DMA_Channel_7。
#define DMA_Channel_0                     ((uint32_t)0x00000000)
#define DMA_Channel_1                     ((uint32_t)0x02000000)
#define DMA_Channel_2                     ((uint32_t)0x04000000)
#define DMA_Channel_3                     ((uint32_t)0x06000000)
#define DMA_Channel_4                     ((uint32_t)0x08000000)
#define DMA_Channel_5                     ((uint32_t)0x0A000000)
#define DMA_Channel_6                     ((uint32_t)0x0C000000)
#define DMA_Channel_7                     ((uint32_t)0x0E000000)

DMA_PeripheralBaseAddr

用来设置 DMA 传输的外设基地址

u8 SendBuff[SEND_BUF_SIZE];	//发送数据缓冲区
(u32)&USART1->DR
(u32)SendBuff

DMA_Memory0BaseAddr

内存基地址,也就是我们存放 DMA 传输数据的内存地址。

DMA_DIR

设置数据传输方向,决定是从外设读取数据到内存还送从内存读取数据发送到外设,也就是外设是源地还是目的地。

#define DMA_DIR_PeripheralToMemory        ((uint32_t)0x00000000)
#define DMA_DIR_MemoryToPeripheral        ((uint32_t)0x00000040) 
#define DMA_DIR_MemoryToMemory            ((uint32_t)0x00000080)

何为外设?
外设指的是单片机外部的外围功能模块,STM32的基本外设有:GPIO(基本输入输出接口),Timer/Counter(定时器和计数器),USART(串行收发处理器),I2C(串行总线),SPI(串行外设接口,使用SPI协议,可能能直接通过串口控制外设),I2S(集成电路的内置音频总线),SD卡接口(闪存卡接口),SDIO(和usb相似,兼容SD卡,可以接wifi模块),USB接口

DMA_BufferSize

设置一次传输数据量的大小,这个很容易理解。

const u8 TEXT_TO_SEND[]={"ALIENTEK Explorer STM32F4 DMA 串口实验"};	
 #define SEND_BUF_SIZE 8200	
 //发送数据长度,最好等于sizeof(TEXT_TO_SEND)+2的整数倍.

sizeof看这里

DMA_PeripheralInc

设置传输数据的时候外设地址是不变还是递增。如果设置为递增,那么下一次传输的时候地址加 1

#define DMA_PeripheralInc_Enable          ((uint32_t)0x00000200)
#define DMA_PeripheralInc_Disable         ((uint32_t)0x00000000)
  • 因为我们是一直往固定外设地址&USART1->DR发送数据,所以地址不递增,值为 DMA_PeripheralInc_Disable;

DMA_MemoryInc

设置传输数据时候内存地址是否递增。这个参数DMA_PeripheralInc 意思接近,只不过针对的是内存。

#define DMA_MemoryInc_Enable              ((uint32_t)0x00000400)
#define DMA_MemoryInc_Disable             ((uint32_t)0x00000000)
  • 场景是将内存中连续存储单元的数据发送到串口,毫无疑问内存地址是需要递增的,所以值为 DMA_MemoryInc_Enable。

DMA_PeripheralDataSize

DMA_PeripheralDataSize 用来设置外设的数据长度是为字节传输(8bits),半字传输(16bits)还是字传输 (32bits)

#define DMA_PeripheralDataSize_Byte       ((uint32_t)0x00000000) 
#define DMA_PeripheralDataSize_HalfWord   ((uint32_t)0x00000800) 
#define DMA_PeripheralDataSize_Word       ((uint32_t)0x00001000)

这里我们是 8 位字节传输,所以 值设置为DMA_PeripheralDataSize_Byte。

DMA_MemoryDataSize

是用来设置内存的数据长度,和第七个参数意思接近

#define DMA_MemoryDataSize_Byte           ((uint32_t)0x00000000) 
#define DMA_MemoryDataSize_HalfWord       ((uint32_t)0x00002000) 
#define DMA_MemoryDataSize_Word           ((uint32_t)0x00004000)

DMA_Mode

用来设置 DMA 模式是否循环采集

#define DMA_Mode_Normal                   ((uint32_t)0x00000000) 
#define DMA_Mode_Circular                 ((uint32_t)0x00000100)
  • 比如我们要从内存中采集 64 个字节发送到串口,如果设置为重复采集,那么它会在 64 个字节采集完成之后继续从内存的第一个地址采集,如此循环。如果设置此参数为循环采集,那么你会看到串口不停的打印数据,不会中断

  • 如果设置为一次连续采集完成之后不循环。所以设置值为 DMA_Mode_Normal。

DMA_Priority

用来设置 DMA 通道的优先级,有低,中,高,超高三种模式。
假设有多个数据流开启(最多 8 个),那么就要设置优先级了

  • DMA 仲裁器将根据这些优先级的设置来决定先执行那个数据流的 DMA。优先级越高的,越早执行,当优先级相同的时候,根据硬件上的编号来决定哪个先执行(编号越小越优先)。
  • 一般选择Medium就可以了。
#define DMA_Priority_Low                  ((uint32_t)0x00000000)
#define DMA_Priority_Medium               ((uint32_t)0x00010000) 
#define DMA_Priority_High                 ((uint32_t)0x00020000)
#define DMA_Priority_VeryHigh             ((uint32_t)0x00030000)

DMA_FIFOMode

用来设置是否开启 FIFO 模式。这里我们不开启所以选择DMA_FIFOMode_Disable。

#define DMA_FIFOMode_Disable              ((uint32_t)0x00000000) 
#define DMA_FIFOMode_Enable               ((uint32_t)0x00000004)

DMA_FIFOThreshold

用来选择 FIFO 阈值。根据前面讲解可以为 FIFO 容量的1/4,1/2,3/4 以及 1 倍。

#define DMA_FIFOThreshold_1QuarterFull    ((uint32_t)0x00000000)
#define DMA_FIFOThreshold_HalfFull        ((uint32_t)0x00000001) 
#define DMA_FIFOThreshold_3QuartersFull   ((uint32_t)0x00000002)
#define DMA_FIFOThreshold_Full            ((uint32_t)0x00000003)

DMA_MemoryBurst

用来配置存储器突发传输配置。
可以选择为

  • 4 个节拍的增量突发传输 DMA_MemoryBurst_INC4
  • 8 个节拍的增量突发传输 DMA_MemoryBurst_INC8
  • 16 个街拍的增量突发传输 DMA_MemoryBurst_INC16
  • 单次传输 DMA_MemoryBurst_Single。

MBURST:存储器突发传输配置 (Memory burst transfer configuration)
这些位将由软件置 1 和清零。
00:单次传输
01: INCR4( 4 个节拍的增量突发传输)
10: INCR8( 8 个节拍的增量突发传输)
11: INCR16( 16 个节拍的增量突发传输)
这些位受到保护,只有 EN 为“0”时才可以写入
在直接模式中,当位 EN =“1”时,这些位由硬件强制置为 0x0。

当使用内部 FIFO 时,源和目标数据的数据宽度可以通过DMA_SxCR 寄存器的 PSIZE 和 MSIZE 位(可以是 8、16 或32 位)编程。
当 PSIZE 和 MSIZE 不相等时

DMA 控制器可以产生单次传输或 4 个、8 个和 16 个节拍的增量突发传输。

  • 配置时使用 DMA_SxCR 寄存器中的MBURST[1:0] 和 PBURST[1:0] 位。
  • 突发大小指示突发中的节拍数,而不是传输的字节数。
  • 为确保数据一致性,形成突发的每一组传输都不可分割:在突发传输序列期间,AHB 传输会锁定,并且 AHB 总线矩阵的仲裁器不解除对 DMA 主总线的授权。

当 AHB 外设端口被配置为单次传输时,根据 DMA_SxCR 寄存器 PSIZE[1:0] 位的值,每个 DMA 请求产生一次字节、半字或字的数据传输。
当 AHB 外设端口被配置为突发传输时,根据 DMA_SxCR 寄存器 PBURST[1:0] 和PSIZE[1:0] 位的值,每个 DMA 请求相应地生成 4 个、8 个或 16 个节拍的字节、半字或字的传输。

  • 在直接模式下,数据流只能生成单次传输,而 MBURST[1:0] 和 PBURST[1:0] 位由硬件强制配置。

注意: 仅在使能指针递增模式时允许突发模式:
— 当 PINC 位为“ 0 ”时,也应将 PBURST 位清为“ 00 ”
— 当 MINC 位为“ 0 ”时,也应将 MBURST 位清为“ 00 ”

DMA_PeripheralBurst

用来配置外设突发传输配置。跟前面一个参数DMA_MemoryBurst 作用类似,只不过一个针对的是存储器,一个是外设。

/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = chx; //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMA 外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA 存储器 0 地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = ndtr;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
//外设数据长度:8 位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
//存储器数据长度:8 位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
//外设突发单次传输
DMA_Init(DMA_Streamx, &DMA_InitStructure);//初始化 DMA Stream

使能串口DMA发送

进行 DMA 配置之后,我们就要开启串口的 DMA 发送功能,使用的函数是:

USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);

如果是要使能串口 DMA 接受,那么第二个参数修改为 USART_DMAReq_Rx 即可。

使能DMA1 通道4 ,启动传输

使能串口 DMA 发送之后,我们接着就要使能 DMA 传输通道:

DMA_Cmd(DMA_CHx, ENABLE);

通过以上 3 步设置,我们就可以启动一次 USART1 的 DMA 传输了。

F407使能 DMA2数据流7,启动传输

使能 DMA 数据流的函数为:
void DMA_Cmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState)
使能 DMA2_Stream7,启动传输的方法为:

DMA_Cmd (DMA2_Stream7,ENABLE);

通过以上 4 步设置,我们就可以启动一次 USART1 的 DMA 传输了。

查询 DMA 传输状态

在 DMA 传输过程中,我们要查询 DMA 传输通道的状态,使用的函数是:

FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)

比如我们要查询 DMA 通道 4 传输是否完成,方法是:

DMA_GetFlagStatus(DMA2_FLAG_TC4);

这里还有一个比较重要的函数就是获取当前剩余数据量大小的函数:

uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx)

比如我们要获取 DMA 通道 4 还有多少个数据没有传输,方法是:

DMA_GetCurrDataCounter(DMA1_Channel4);

F407查询

在 DMA 传输过程中,我们要查询 DMA 传输通道的状态,使用的函数是:

DMA_GetFlagStatus

FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)

比如我们要查询 DMA 数据流 7 传输是否完成,方法是:

DMA_GetFlagStatus(DMA2_Stream7,DMA_FLAG_TCIF7);

这里还有一个比较重要的函数就是获取当前剩余数据量大小的函数:

DMA_GetCurrDataCounter

uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx);

比如我们要获取 DMA 数据流 7 还有多少个数据没有传输,方法是:

DMA_GetCurrDataCounter(DMA1_Channel4);

DMA_SetCurrDataCounter

同样,我们也可以设置对应的 DMA 数据流传输的数据量大小,函数为:

void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter);

DMA_GetCmdStatus

while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//等待DMA可配置 

DMA_DeInit

DMA_DeInit(DMA_Streamx);

DMA 相关的库函数我们就讲解到这里,大家可以查看固件库中文手册详细了解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万码无虫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值