【STM32】关于DMA控制器的介绍和使用
文章目录
- 前言
- 1、什么是DMA控制器
- 2、DMA控制器的工作流程及特性
- 3、STM32DMA控制器的初始化流程
- 4、软件设计
前言
DMA控制器的使用是提升STM32数据传输效率的一个重要途径
1、什么是DMA控制器
DMA,全称为:Direct Memory Access
,即直接存储器访问,DMA 传输将数据从一个地址空间复制到另外一个地址空间。当 CPU 初始化这个传输动作,传输动作本身是由DMA 控制器 来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工作。DMA 传输对于高效能嵌入式系统算法和网络是很重要的。DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。
2、DMA控制器的工作流程及特性
▲DMA控制器工作流程
工作流程:
从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址是DMA_CPARx
或DMA_CMARx
寄存器指定的外设基地址或存储器单元;存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx
或DMA_CMARx
寄存器指定的外设基地址或存储器单元;执行一次DMA_CNDTRx
寄存器的递减操作,该寄存器包含未完成的操作数目。
工作流程中涉及寄存器相关信息:
DMA_CPARx(外设(peripheral device)地址寄存器)
:该寄存器用来存储 STM32 外设的地址,若串口 1,该寄存器须写入 0x40013804(就是&USART1_DR)。
DMA_CMARx(存储器(memory)地址寄存器)
:该寄存器是用来放存储器的地址的。编程时可使用SendBuf[5200]数组来做存储器,那么在DMA_CMARx 中写入&SendBuff 即可。
DMA_CNDTRx(传输数据量寄存器)
:这个寄存器控制 DMA 通道 x 的每次传输所要传输的数据量。其设置范围为 0~65535
。并且该寄存器的值会随着传输的进行而减少,当该寄存器的值为 0 的时候就代表此次数据传输已经全部发送完成了。所以可以通过这个寄存器的值来知道当前 DMA 传输的进度。
如果我要在数据传输完成时及时做操作怎么办?
这时候不由得会想起中断这个东西,显然DMA控制器也可以触发中断,而且还有很多种考虑得很周全。
▲DMA-ISR寄存器
若开启了 DMA_ISR
中这些中断,在达到条件后就会跳到中断服务函数里面去。当然也可以通过查询方式来得知事件得发生。
那么这些中断标志位要如何清除呢?
▲DMA-IFCR寄存器
配置通道的寄存器在哪里?
DMA_CCRx(DMA 通道 x 配置寄存器)
:该寄存器控制着 DMA 的很多相关信息,包括数据宽度、外设及存储器的宽度、通道优先级、增量模式、传输方向、中断允许、使能等都是通过该寄存器来设置的。所以 DMA_CCRx 是 DMA 传输的核心控制寄存器。
▲外设-通道映射表
总结特性:
●每个通道都直接连接专用的硬件 DMA 请求,每个通道都同样支持软件触发。这些功能通过软件来配置。
●在七个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),假如在相等优先权时由硬件决定(请求 0 优先于请求 1,依此类推) 。
●独立的源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
●支持循环的缓冲器管理
●每个通道都有 3 个事件标志(DMA 半传输,DMA 传输完成和 DMA 传输出错),这 3 个事件标志逻辑或成为一个单独的中断请求。
●存储器和存储器间的传输
●外设和存储器,存储器和外设的传输
●闪存、SRAM、外设的 SRAM、APB1 APB2 和 AHB 外设均可作为访问的源和目标。
●可编程的数据传输数目:最大为 65536
3、STM32DMA控制器的初始化流程
1)使能 DMA 时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能 DMA 时钟
2)初始化 DMA 通道 4 参数
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)
3)使能串口 DMA 发送
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
4)使能 DMA1 通道 4,启动传输。
DMA_Cmd(DMA_CHx, ENABLE);
查询DMA状态相关函数:
查询 DMA 传输通道的状态:FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);
返回当前 DMA 通道 x 剩余的待传输数据数目:uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
4、软件设计
DMA.c:
DMA_InitTypeDef DMA_InitStructure;u16 DMA1_MEM_LEN;//保存DMA每次数据传送的长度
//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_CHx:DMA通道CHx
//cpar:外设地址
//cmar:存储器地址
//cndtr:数据传输量
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值DMA1_MEM_LEN=cndtr;DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设基地址DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小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通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输DMA_Init(DMA_CHx, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器}
//开启一次DMA传输
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{ DMA_Cmd(DMA_CHx, DISABLE ); //关闭USART1 TX DMA1 所指示的通道 DMA_SetCurrDataCounter(DMA_CHx,DMA1_MEM_LEN);//DMA通道的DMA缓存的大小DMA_Cmd(DMA_CHx, ENABLE); //使能USART1 TX DMA1 所指示的通道
}
功能:按下按键使用串口1用DMA1_Channel4传输数据并且显示其传输进度。
main.c:
#define SEND_BUF_SIZE 8200 //发送数据长度,最好等于sizeof(TEXT_TO_SEND)+2的整数倍.u8 SendBuff[SEND_BUF_SIZE]; //发送数据缓冲区
const u8 TEXT_TO_SEND[]={"ALIENTEK WarShip STM32F1 DMA 串口实验"};
......
while(1)
{t=KEY_Scan(0);if(t==KEY0_PRES)//KEY0按下{LCD_ShowString(30,150,200,16,16,"Start Transimit....");LCD_ShowString(30,170,200,16,16," %");//显示百分号printf("\r\nDMA DATA:\r\n"); USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送 MYDMA_Enable(DMA1_Channel4);//开始一次DMA传输! //等待DMA传输完成,此时我们来做另外一些事,点灯//实际应用中,传输数据期间,可以执行另外的任务while(1){if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=RESET) //判断通道4传输完成{DMA_ClearFlag(DMA1_FLAG_TC4);//清除通道4传输完成标志break; }pro=DMA_GetCurrDataCounter(DMA1_Channel4);//得到当前还剩余多少个数据pro=1-pro/SEND_BUF_SIZE;//得到百分比 pro*=100; //扩大100倍LCD_ShowNum(30,170,pro,3,16); } LCD_ShowNum(30,170,100,3,16);//显示100% LCD_ShowString(30,150,200,16,16,"Transimit Finished!");//提示传送完成}i++;delay_ms(10);if(i==20){LED0=!LED0;//提示系统正在运行 i=0;}
}
......
【STM32】关于DMA控制器的介绍和使用相关推荐
- STM32系列微控制器入门介绍
文章目录 目的 基础需求 电路基础 编程语言 入门介绍 官方网站 型号选择 开发方式 开发工具 程序调试 固件烧录 资料说明 总结 目的 STM32是意法半导体(ST)推出的主要基于ARM Corte ...
- STM32学习笔记——DMA控制器(向原子哥学习)
一.DMA简介 DMA,全称为:Direct Memory Access,即直接存储器访问,DMA 用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输.当 CPU 初始化这个传输动作,传输 ...
- stm32 文件系统dma大小_「正点原子NANO STM32F103开发板资料连载」第二十二章 DMA 实验...
1)实验平台:[正点原子] NANO STM32F103 开发板 2)摘自<正点原子STM32 F1 开发指南(NANO 板-HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 ...
- STM32 FFT DMA ADC THD
利用STM32 FFT算法计算THD 一.设备准备 -->粤嵌STM32F429IGT6开发板 1块 -->串口调试助手 二.FFT算法意义 使用FFT算法,是为了获取信号在频域的相关参数 ...
- 【STM32】 DMA原理,步骤超细详解,一文看懂DMA
如需转载请注明地址:https://blog.csdn.net/as480133937/article/details/104927922 DMA的基本介绍 什么是DMA (DMA的基本定义) DMA ...
- STM32】 DMA原理,步骤超细详解,一文看懂DMA
如需转载请注明地址:https://blog.csdn.net/as480133937/article/details/104927922 DMA的基本介绍 什么是DMA (DMA的基本定义) DMA ...
- STM32 之 DMA
stm32f2 技术培训_直接存储器访问_dma http://www.doc88.com/p-7952436689372.html AN4031 应用笔记:使用 STM32F2 和 STM32F4 ...
- dma接收双缓存 stm32_容易被大多数人忽视的STM32串口DMA问题
讨论三个问题: 1.什么叫串口DMA 请求: 2.串口简要复习: 3.串口DMA发送流程. 第一 什么叫串口DMA 请求(战舰STM32开发板) 说这个问题之前先简单回顾DMA的基本特性.先导出原子哥 ...
- 【STM32】DMA程序示例
00. 目录 文章目录 00. 目录 01. DMA简介 02. 功能描述 03. 硬件设计 04. 程序设计 05. 结果验证 06. 附录 07. 声明 01. DMA简介 DMA,全称为:Dir ...
- 【STM32】DMA相关函数和类型
00. 目录 文章目录 00. 目录 01. DMA简介 02. 相关类型 03. 相关函数 04. 结构体封装 05. 预留 06. 附录 07. 声明 01. DMA简介 DMA,全称为:Dire ...
最新文章
- STM32串口接收数据
- 计算机导论成绩分为几部分,计算机导论复习题(选择部分)汇总.docx
- MySQL优化之my.conf配置详解
- httpclient4 中文版帮助文档,最新官方版翻译版(第一章 上)
- python生成4位验证码_Python 生成4位验证码图片
- 【源码】斗地主人机对战程序算法2012完整版
- Matlab--三种归一化方法
- js的正则表达,只允许数字和特殊
- 疫情当前,华为云数据库携手WeLink保障企业云上办公数据稳定可靠
- windows中的凭据管理
- rdesktop连接windows远程桌面详解
- Anaconda如何更新pip
- dos2unix整个目录
- Redis缓存雪崩解决方案
- 千兆路由器和百兆路由器
- 涡扇发动机的预测性维护
- 物联网嵌入式——学习分享
- Android ScrollView 长截屏
- 豆果美食批量发布菜谱软件
- 一篇关于不同进制之间的转换、比如二进制、八进制、十进制、十六进制等
热门文章
- WINDOWS虚拟内存设置
- CSDN 空间:“迷你博客”很迷人(2)
- OpenCV笔记之六(4)——图像处理之颜色通道拆分、合并及颜色空间
- 斯坦福大学公开课:量子力学
- 如何运行element ui
- 基于matlab的排队系统仿真
- 无法解析 taglibs:standard:1.1.2
- ERROR: Cannot uninstall 'wrapt'. It is a distutils installed project and thus we cannot accurately
- P5_扩展卡尔曼滤波器_udacity无人驾驶
- 14期-连肝7个晚上,总结了计算机网络的知识点!(共66条)