文章目录
- DMA介绍
- F407的DMA有多少数据流与通道?
- F407的DMA如何判定DMA请求的优先级?
- DMA框图
- F407的DMA源和目的的可选项?
- F407DMA的主要特性
- 源与目的的方向配置
- DMA必要性
- 仲裁器
- F407每个数据流对应请求映射
- DMA结构
- DMA相关寄存器
- DMA 中断状态寄存器(DMA_ISR)
- DMA 中断标志清除寄存器(DMA_IFCR)
- DMA 通道 x 配置寄存器(DMA_CCRx)
- DMA 通道 x 传输数据量寄存器(DMA_CNDTRx)
- DMA 通道 x 的外设地址寄存器(DMA_CPARx)
- DMA 通道 x 的存储器地址寄存器(DMA_CMARx)
- DMA通道配置步骤
- DMA传输原理
- F407 使能DMA 时钟
- DAM复位
- F407 DMA通道参数
- DMA_Channel
- DMA_PeripheralBaseAddr
- DMA_Memory0BaseAddr
- DMA_DIR
- DMA_BufferSize
- DMA_PeripheralInc
- DMA_MemoryInc
- DMA_PeripheralDataSize
- DMA_MemoryDataSize
- DMA_Mode
- DMA_Priority
- DMA_FIFOMode
- DMA_FIFOThreshold
- DMA_MemoryBurst
- DMA_PeripheralBurst
- 使能串口DMA发送
- 使能DMA1 通道4 ,启动传输
- F407使能 DMA2数据流7,启动传输
- 查询 DMA 传输状态
- F407查询
泉水
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每个数据流对应请求映射
一对多的关系
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 传输通道的状态,使用的函数是:
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)
比如我们要查询 DMA 数据流 7 传输是否完成,方法是:
DMA_GetFlagStatus(DMA2_Stream7,DMA_FLAG_TCIF7);
这里还有一个比较重要的函数就是获取当前剩余数据量大小的函数:
uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx);
比如我们要获取 DMA 数据流 7 还有多少个数据没有传输,方法是:
DMA_GetCurrDataCounter(DMA1_Channel4);
同样,我们也可以设置对应的 DMA 数据流传输的数据量大小,函数为:
void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter);
DMA 相关的库函数我们就讲解到这里,大家可以查看固件库中文手册详细了解。