IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> DMA学习笔记 -> 正文阅读

[嵌入式]DMA学习笔记

DMA 即直接存储器访问。 DMA传输将数据从一个地址空间复制到另一个地址空间。当CPU初始化这个传输动作(即我们初始化好DMA后),传输动作本身是由DMA控制器来实现和完成的(这一系列传输的动作不需要经过cpu)。 DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。 作用:为CPU减负。

STM32F4最多有2个DMA控制器,每个DMA控制器有8个数据流。每个DMA控制器都用于管理一个或者多个外设的存储器访问请求。每个数据流总共可以有多达8个通道(或请求)(但是一个数据流一次只能传输一个通道的数据,虽然每个数据流可以有八个通道,但是一次只能处理它下面的一个通道),每个通道都有一个仲裁器,用于处理DMA请求间的优先级。

DMA框图:

?DMA传输时(什么发出的)对DMA控制器发出请求
?DMA控制器收到请求,触发DMA工作
?DMA控制器从AHB获取数据,存储到DMA通道中
?DMA控制器的DMA使用AHB把数据经由DMA通道(使用AHB经过DMA通道是怎么理解??)存放到外设、储存器中,这个数据的传输过程中,完全不需要内核的参与,也就是不需要CPU的参与

DMA 主要特性是:
? 双 AHB 主总线架构,一个用于存储器访问,另一个用于外设访问
? 仅支持 32 位访问的 AHB 从编程接口
? 每个 DMA 控制器有 8 个数据流,每个数据流有多达 8 个通道(或称请求)
? 每个数据流有单独的四级 32 位先进先出存储器缓冲区 (FIFO) ,可用于 FIFO 模式或直接模式:
— FIFO 模式:可通过软件将阈值级别选取为 FIFO 大小的 1/4 1/2 3/4
—直接模式:每个 DMA 请求会立即启动对存储器的传输。当在直接模式(禁止 FIFO )下将 DMA
请求配置为以存储器到外设模式传输数据时, DMA 仅会将一个数据从存储器预加载到内部 FIFO ,从而确保一旦外设触发 DMA 请求时则立即传输数据。
? 通过硬件可以将每个数据流配置为:
—支持外设到存储器、存储器到外设和存储器到存储器传输的常规通道
—也支持在存储器方双缓冲的双缓冲区通道
? 8 个数据流中的每一个都连接到专用硬件 DMA 通道(请求)
? DMA 数据流请求之间的优先级可用软件编程( 4 个级别:非常高、高、中、低),在软件优先级相同的情况下可以通过硬件决定优先级(例如,请求 0 的优先级高于请求 1
? 每个数据流也支持通过软件触发存储器到存储器的传输(仅限 DMA2 控制器)
? 可供每个数据流选择的通道请求多达 8 个。此选择可由软件配置,允许几个外设启动 DMA 请求
? 要传输的数据项的数目可以由 DMA 控制器或外设管理:
— DMA 流控制器:要传输的数据项的数目是 1 65535 ,可用软件编程(我们事先规定好要传输多少的数据,比如100,当传输完100个数据的时候,才会结束DMA的数据传输
—外设流控制器:要传输的数据项的数目未知并由源或目标外设控制,这些外设通过硬件发出传输结束的信号
独立的源和目标传输宽度(字节8位、半字16位、字32位):源和目标的数据宽度不相等时, DMA 自动封装/ 解封必要的传输数据来优化带宽。这个特性仅在 FIFO 模式下可用(比如源的数据宽度是8位,目标的数据宽度是32位,DMA就会将数据先存放在FIFO中,当FIFO中存放了4个数据32位的时候,就一次性传送给目标。
? 对源和目标的增量或非增量寻址
? 支持 4 个、 8 个和 16 个节拍的增量突发传输。突发增量的大小可由软件配置,通常等于外设 FIFO 大小的一半
? 每个数据流都支持循环缓冲区管理
? 5 个事件标志( DMA 半传输、 DMA 传输完成、 DMA 传输错误、 DMA FIFO 错误、直接模式错误),进行逻辑或运算,从而产生每个数据流的单个中断请求

?

?

?DMA_SxPAR用于存放外设地址;DMA_SxM0AR用于存放存储器地址;比如说我要从外设传输数据到存储器,那么就要源地址的设置就要去设置DMA_SxPAR寄存器,而目标地址的设置就要去设置DMA_SxM0AR寄存器。

?

?

?这里存储器到存储器,第一个存储器的地址是用的DMA_SxPAR设置的。

DMA_SxCR寄存器:?????????????????????????

?DMA_SxCR寄存器? :? ? ? ?

?

DMA_SxCR寄存器:?比如要传100个数据,当100个数据传输完成之后,自动再加载100到寄存器,去响应DMA的请求

?

?PSIZE:外设;MSIZE:存储器;

?有两个源,源1和源2。一个目标。当源1在进行传输数据给目标的时候,可以向源2填充数据,当源1数据传输结束就可以进行源2的数据传输。

?DMA配置程序过程(串口发送DMA)

使能DMA时钟 ? ?RCC_AHB1PeriphClockCmd();

初始化DMA通道参数 ? ?DMA_Init();

使能串口DMA发送,串口DMA使能函数: ? USART_DMACmd();

查询DMA的EN位,确保数据流就绪,可以配置 ? ?DMA_GetCmdStatus();

设置通道当前剩余数据量 ? ?DMA_SetCurrDataCounter();

使能DMA1通道,启动传输。 ? ?DMA_Cmd();

查询DMA传输状态 ? DMA_GetFlagStatus();

获取/设置通道当前剩余数据量: ? DMA_GetCurrDataCounter();

?

常用的DMA库函数 :(在dma的头文件中)

void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx, DMA_InitTypeDef* DMA_InitStruct);
void DMA_Cmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState);

void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter);
uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx);

void DMA_DoubleBufferModeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t Memory1BaseAddr,uint32_t DMA_CurrentMemory);
void DMA_DoubleBufferModeCmd();
void DMA_MemoryTargetConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t MemoryBaseAddr, uint32_t DMA_MemoryTarget);
uint32_t DMA_GetCurrentMemoryTarget(DMA_Stream_TypeDef* DMAy_Streamx);

FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef* DMAy_Streamx);
uint32_t DMA_GetFIFOStatus(DMA_Stream_TypeDef* DMAy_Streamx);
FlagStatus DMA_GetFlagStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG);
void DMA_ClearFlag(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG);
void DMA_ITConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT, FunctionalState NewState);
ITStatus DMA_GetITStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT);
void DMA_ClearITPendingBit(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT);

常用的外设DMA使能库函数:(在对应的外设头文件中,eg:ADC_DMACmd()函数就在adc的头文件中间找)

void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq,FunctionalState NewState);
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState);
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void SDIO_DMACmd(FunctionalState NewState);
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq,FunctionalState NewState);

void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength)
void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource,FunctionalState NewState);

void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx,DMA_InitTypeDef* DMA_InitStruct)

?

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_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; 外设的突发传输

设置传输数据长度? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter);

获取剩余传输数据长度
uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx);

判断是否有其他的数据流在运行? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef* DMAy_Streamx);

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-11 12:52:08  更:2021-11-11 12:52:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:48:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码