历史上的今天
今天是:2024年09月02日(星期一)
2019年09月02日 | STM32开发 -- Git的详细使用
2019-09-02 来源:eefocus
在GPS部分有用到DMA,接下来看一下它的使用。
一、DMA简介
直接存储器存取(DMA) 用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。
两个DMA控制器有12个通道(DMA1有7个通道, DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。
二、DMA主要特性
● 12个独立的可配置的通道(请求): DMA1有7个通道, DMA2有5个通道
● 每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置。
● 在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推) 。
● 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
● 支持循环的缓冲器管理
● 每个通道都有3个事件标志(DMA半传输、 DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求。
● 存储器和存储器间的传输
● 外设和存储器、存储器和外设之间的传输
● 闪存、 SRAM、外设的SRAM、 APB1、 APB2和AHB外设均可作为访问的源和目标。
● 可编程的数据传输数目:最大为65535
三、功能框图

四、DMA请求映像
DMA1控制器
从外设(TIMx[x=1、 2、 3、 4]、 ADC1、 SPI1、 SPI/I2S2、 I2Cx[x=1、 2]和USARTx[x=1、 2、 3])产生的7个请求,通过逻辑或输入到DMA1控制器,这意味着同时只能有一个请求有效。外设的DMA请求,可以通过设置相应外设寄存器中的控制位,被独立地开启或关闭。


DMA2控制器
从外设(TIMx[5、 6、 7、 8]、 ADC3、 SPI/I2S3、 UART4、 DAC通道1、 2和SDIO)产生的5个请求,经逻辑或输入到DMA2控制器,这意味着同时只能有一个请求有效。参见下图的DMA2请求映像。外设的DMA请求,可以通过设置相应外设寄存器中的DMA控制位,被独立地开启或关闭。
注意: DMA2控制器及相关请求仅存在于大容量产品和互联型产品中。


五、相关寄存器
DMA中断状态寄存器(DMA_ISR)


如果开启了 DMA_ISR 中这些中断,在达到条件后就会跳到中断服务函数里面去,即使没开启,我们也可以通过查询这些位来获得当前 DMA 传输的状态。这里我们常用的是 TCIFx,即通道 DMA 传输完成与否的标志。注意此寄存器为只读寄存器,所以在这些位被置位之后,只能通过其他的操作来清除。
DMA中断标志清除寄存器(DMA_IFCR)

DMA_IFCR 的各位就是用来清除 DMA_ISR 的对应位的,通过写 1 清除。在 DMA_ISR 被置位后,我们必须通过向该位寄存器对应的位写入 1 来清除。
其他寄存器
自行查看《STM32中文参考手册_V10.pdf》 150页
六、DMA配置
举个栗子:
需要配置USART2 的DMA接收,DMA该怎么配置。
查看上面介绍的得出:
USART2_RX 在DMA1的通道 6,USART2是挂载在 APB1 下面的外设。
然后就可以配置了:
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA1时钟
USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE); //打开串口2 DMA接收使能 开启串口DMA接收
DMA_DeInit(DMA1_Channel6); //恢复缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR); //设置USART2发送数据寄存器
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buf; //设置发送缓冲区首地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //设置外设位目标,内存缓冲区->外设寄存器
DMA_InitStructure.DMA_BufferSize = BufferSize; //需要发送的字节数
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不做增加调整,调整不调整都是DMA自动实现的
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存缓冲区地址增加调整
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据宽度8位,1个字节
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存数据宽度8位,1个字节
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //单次传输模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //优先级设置
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //关闭内存到内存的DMA模式
DMA_Init(DMA1_Channel6, &DMA_InitStructure); //写入配置
DMA_Cmd(DMA1_Channel6, ENABLE); //开启DMA通信,等待接收数据
七、使用
一个比较重要的函数,获取当前剩余数据量大小:
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx)
则:
先配置DMA
GpsRxDMACfg( GpsTransferBuffer,DEF_GPS_RBUFSIZE );
//GpsTransferBuffer为接收buffer,DEF_GPS_RBUFSIZE 为设置的接收buffer大小(512)
根据设置的接收buff大小减去当前剩余数据量,得到当前接收数据大小。
curcount = DEF_GPS_RBUFSIZE - DMA_GetCurrDataCounter( GPS_RxDMA_Ch );
史海拾趣
|
生动形象的教学用电子钟[ZT] 笔者在教学中,设计了一套教学实验用“电子钟”电路。此线路包括七段数码显示器BS205和循环彩灯电路,实验显示生动有趣,各部分原理简单,适宜学生直接观察“编码器”、“译码器”、“寄存器”、“计数器”等逻辑 ...… 查看全部问答> |
|
关于TQ2440触摸屏的应用设计。现在能够实现触摸屏界面的旋转,想添加一些其它的应用功能,请问能不能把显示界面缩小,即原来3.5寸屏的界面,显示为1.75寸的区域,这种功能能够实现吗?如果实现需要涉及那些方面?… 查看全部问答> |
|
我在flash上烧写的镜像文件为 NK.BIN, 我在注册表中添加如下: ; Bind BINFS to the block driver [HKEY_LOCAL_MACHINE\\System\\StorageManager\\Profiles\\FlashDrv] \"DefaultFileSystem\"=\"BINFS\" \"Partition ...… 查看全部问答> |
|
我用的是keil. 遇到到 PA4, PA5 , PA6,PA7 等无法设置输出状态. 在keil的调试状态就感觉无**常设置.而引脚设置跟附近的一样,看起来没错. 但无**常设置.其他的比如PC5~PC7等就没有问题. 初始化的语句:应该没有问题. GPIO_Ini ...… 查看全部问答> |
|
下载 (108.1 KB) 2011-1-19 15:42 我现在在做微功耗,用的是待机模式,我在看微功耗的待机模式的启动项中,有个启动方式是IWDG,但是这中启动方式我没有办法跟踪,我在手册中看到可以检测复位标记来判断是什么方式复位 ...… 查看全部问答> |
|
#include<msp430x44x.h> interrupt[TIMERA0_VECTOR] void Timer_A(void) { ~~~ } void InitSystem(void) { ~~~ //TIME_A TACTL=ID1+TASSEL1+TACLR+ ...… 查看全部问答> |
|
有没有3v可用的数码管驱动芯片?或者怎么用电池给5v的74门供电? 想做个数字钟,但是找不到3v可用的数码管驱动芯片,找到了淘宝上也没卖的。 另外就是考虑怎么给3v/5v元件混合电路用AA电池供电……… 查看全部问答> |




