stm32专题十三:DMA(一)结构框图

发布者:闪耀星空最新更新时间:2021-10-21 来源: eefocus关键字:stm32  DMA  结构框图 手机看文章 扫描二维码
随时随地手机看文章

DMA(data memory access)直接存储器访问,和串口USART、GPIO一样,也是一个外设。


把数据从一个地方搬到另一个地方,而不占用CPU。像串口发送数据,数据是一个一个的发。CPU首先把数据从内存(数组)拿到CPU内部的寄存器(CPU内部有一组暂存数据寄存器R1、R2、R3等),然后再发到串口的数据寄存器USART_DR,这些过程一直需要占用CPU。而当我们使用DMA时,如果CPU给DMA一个命令(把数据从内存发到串口),这时DMA就会实现这个功能,整个过程CPU是空闲的,可以去做其他事。比如,点亮一个LED,显示液晶屏LCD等。


DMA支持3种模式:


Memory to Memory (这里的Memory可以是Flash或内部SRAM);

Memory to Peripheral,这个最典型的应用是串口发送;

Peripheral to Memory,这个最典型的应用就是ADC。ADC采集的数据是保存在数据寄存器DR,然后要读到内存;

DMA1有7个通道,DMA2有5个通道。


开始DMA时,以内存—串口为例。首先串口向CPU发送请求,告诉DMA,把数据从内存搬到发送数据寄存器中。这个请求由其中的一方来产生(发送方),通道为传输数据的管道,

有一个比较有意思的问题,就是数据对齐。我们通常要求发送方和接收方的数据长度要一致(数据对齐),但有些时候我们又会使用到不一致的情况(比如8位数据发送到定时器16位CCR寄存器),这时候该怎么办?我看到基本上很少有这种问题的详细解释与实验验证,但其实在中文参考手册中是有相关描述的。可以看到,对于DMA对齐的数据,直接操作没有问题。而当DMA数据不对其,比如8位传到16位时,如 DMA读到的8位数据为B0,实际写入的会是00B0,高8位用0补齐。当16位转8位数据时,如DMA读到B1B0,在写入时会把高8位丢弃,只写入B0位。这跟C语言的强制类型转换一致。

为了验证这个DMA数据不对齐配置是否正确,使用stm32CubeMX进行了一次测试(8位数据从内存传到16位CCR寄存器),配置如下,实验结果正确。

DMA每个通道具体对应的外设,可以看到,连接在同一通道上的外设,DMA请求同时只能有有一个生效。同理,DMA发送数据时,每个通道只能用作其中的一种。例如:DMA1通道1,任何时刻,只能作为ADC1 TIM2_CH3 TIM4_CH1中的一个数据管道。这里说的只是M-P和P-M,当使用M-M时,所有的通道都可以随意使用。

当有多个DMA请求一起来,就需要仲裁器来仲裁,到底哪个DMA请求先执行,这个在中文参考手册中有很详细的说明,具体如下:

那么我们就知道了,当多个DMA请求一起来时,先比较软件阶段,这里由DMA_CCRx寄存器的PL位分成4个等级,根据软件等级可以确定发送顺序。如果情况更加复杂,如有7路DMA请求,此时4个等级明显不够用,一定会出现等级相同的情况。此时,则比较硬件通道编号,编号越小等级越高。

标准固件库中的dma初始化结构体:


/** 

  * @brief  DMA Init structure definition

  */

 

typedef struct

{

  // 外设基地址

  uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */

 

 // 存储器基地址  

uint32_t DMA_MemoryBaseAddr;     /*!< Specifies the memory base address for DMAy Channelx. */

 

// DMA传输方向(M-P  P-M)  

uint32_t DMA_DIR;                /*!< Specifies if the peripheral is the source or destination.

                                        This parameter can be a value of @ref DMA_data_transfer_direction */

 

// DMA传输的数据量(注意,不是字节数,如4个uint16_t,就是4,不是8)

uint32_t DMA_BufferSize;         /*!< Specifies the buffer size, in data unit, of the specified Channel. 

                                        The data unit is equal to the configuration set in DMA_PeripheralDataSize

                                        or DMA_MemoryDataSize members depending in the transfer direction. */

 

// 外设地址递增  

uint32_t DMA_PeripheralInc;      /*!< Specifies whether the Peripheral address register is incremented or not.

                                        This parameter can be a value of @ref DMA_peripheral_incremented_mode */

 

// 存储器地址递增  

uint32_t DMA_MemoryInc;          /*!< Specifies whether the memory address register is incremented or not.

                                        This parameter can be a value of @ref DMA_memory_incremented_mode */

 

  // DMA外设数据宽度(字节,半字,字),通常要与存储器数据宽度对齐(也可以不对齐)

  // 如果数据宽度不对齐,按前面说的C语言规则处理

  uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width.

                                        This parameter can be a value of @ref DMA_peripheral_data_size */

 

  // 存储器数据宽度

  uint32_t DMA_MemoryDataSize;     /*!< Specifies the Memory data width.

                                        This parameter can be a value of @ref DMA_memory_data_size */

 

  // DMA模式(普通和循环模式)

  uint32_t DMA_Mode;               /*!< Specifies the operation mode of the DMAy Channelx.

                                        This parameter can be a value of @ref DMA_circular_normal_mode.

                                        @note: The circular buffer mode cannot be used if the memory-to-memory

                                              data transfer is configured on the selected Channel */

 

  // DMA优先级(最高/高/中/低)

  uint32_t DMA_Priority;           /*!< Specifies the software priority for the DMAy Channelx.

                                        This parameter can be a value of @ref DMA_priority_level */

 

  // 是否使能存储器到存储器模式

  uint32_t DMA_M2M;                /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer.

                                        This parameter can be a value of @ref DMA_memory_to_memory */

}DMA_InitTypeDef;

DMA可以设置三种中断,传输完成中断、传输过半中断、传输错误中断。


/**

  * @brief  Enables or disables the specified DMAy Channelx interrupts.

  * @param  DMAy_Channelx: where y can be 1 or 2 to select the DMA and 

  *   x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel.

  * @param  DMA_IT: specifies the DMA interrupts sources to be enabled

  *   or disabled. 

  *   This parameter can be any combination of the following values:

  *     @arg DMA_IT_TC:  Transfer complete interrupt mask

  *     @arg DMA_IT_HT:  Half transfer interrupt mask

  *     @arg DMA_IT_TE:  Transfer error interrupt mask

  * @param  NewState: new state of the specified DMA interrupts.

  *   This parameter can be: ENABLE or DISABLE.

  * @retval None

  */

void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState)

{

  /* Check the parameters */

  assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx));

  assert_param(IS_DMA_CONFIG_IT(DMA_IT));

  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)

  {

    /* Enable the selected DMA interrupts */

    DMAy_Channelx->CCR |= DMA_IT;

  }

  else

  {

    /* Disable the selected DMA interrupts */

    DMAy_Channelx->CCR &= ~DMA_IT;

  }

}

关键字:stm32  DMA  结构框图 引用地址:stm32专题十三:DMA(一)结构框图

上一篇:stm32专题十二:DEBUG调试宏 C语言 调试宏
下一篇:stm32专题十三:DMA(二)存储器到存储器

推荐阅读最新更新时间:2024-11-12 14:04

STM32简单任务调度的总结
概述 STM32的开发目前大多数还开处于“裸奔”的阶段,处于开发成本的考虑,可能还未嵌入任何的RTOS系统,由于没有操作系统的支持,因而不能方便的对多任务进行调度和管理。而有的任务不紧急,不需要过多的时间去循环执行,因此需要一个简单的任务调度来解决这个问题。 STM32F103ZE的AHB时钟为72MHz,通过HSE的8M倍频到72M,然后APB1预分频系数为2,所以TIM2-7时钟为2*36M。由于定时器是16位,PSC寄存器最大为65536,不支持71999,所以只能以0.1ms计数。 整个系统在获取时间的累增时,定义64位变量,即可运行很久的时间,不用担心溢出或者死机。定义64位变量有2个方法,一就是用long lo
[单片机]
关于STM32函数定义
1.*(__IO uint8_t *) CIR_BYTE3_ADDRESS #define __IO volatile /*! Defines 'read / write' permissions 声明 volatile ,目的:使编译器不优化该变量。从相应变量内存中取数。 /* Check the parameters */ assert_param(IS_TIM_ALL_PERIPH(TIMx)); //assert _param函数作参数检查用 2. static: static局部变量中文名叫静态局部变量。它与普通的局部变量比起来有如下几个区别: 1)位
[单片机]
STM32 ADC时钟配置
一 STM32 ADC 采样频率的确定 先看一些资料,确定一下STM32 ADC 的时钟: (1),由时钟控制器提供的ADCCLK 时钟和PCLK2(APB2 时钟)同步。CLK 控制器为ADC 时钟提供一个专用的可编程预分频器。 (2)一般情况下在程序 中将 PCLK2 时钟设为 与系统时钟相同 RCC_HCLKConfig(RCC_SYSCLK_Div1); RCC_PCLK2Config(RCC_HCLK_Div1); RCC_PCLK1Config(RCC_HCLK_Div2); (3)在时钟配置寄存器(RCC_CFGR) 中 有 为ADC 时钟提供一个专用的可编程预分器 位15:14 ADCPRE:ADC预分频 由软件设置
[单片机]
如何确认STM32时钟配置是否正确
配置STM32F103时钟(HSI)为48M void SystemClock_Config(void) { RCC_DeInit(); RCC_HSICmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET); RCC_HCLKConfig(RCC_SYSCLK_Div1); RCC_PCLK1Config(RCC_HCLK_Div2); RCC_PCLK2Config(RCC_HCLK_Div1); RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_12);
[单片机]
STM32动态更改PWM波频率和占空比
STM32的PWM波动态调频和调占空比 以TIM3_CH1为例 (1)定时器工作原理 定时器的时基单元包含三个部分:①自动装载寄存器(TIMx_ARR),②预分频器寄存器 (TIMx_PSC),③计数器寄存器(TIMx_CNT)。设置自动装载值,预分频器根据所设置的分频系数(1-65536)对定时器所选择的时钟源进行分频,分频后的频率驱动计数器。计算器开始计数,当计数器达到自动装载值时,重新开始计数! 以秒表举例:时钟源是秒针,经过60分频后的频率变成分针,分针一分钟一分钟的增加,当分针数达到60时,又从零开始计数。在这个例子中,秒针是时钟源,第一个60就是预分频器设置的值,第二个60就是自动装载寄存器设置的值。 (2)P
[单片机]
<font color='red'>STM32</font>动态更改PWM波频率和占空比
基于STM32单片机流水灯控制中的GPIO_Init()函数解析
学习STM32时,首先要熟悉流水灯例程,在这里就来分析流水灯中的GPIO_Init()函数 例如:流水灯例程中使用的端口是macLED1_GPIO_PORT=GPIOB, 控制的引脚是GPIO_Pin_0, 引脚的模式是GPIO_Mode_Out_PP(通用推挽输出), 引脚的速率是GPIO_Speed_50MHz, 用到的寄存器是CRL 将上述的引脚、模式、速率换算成32位的16进制,分别是: 1)控制的引脚是GPIO_Pin_0 换算成32位的16进制是:0x0000 0001 2)引脚的模式是GPIO_Mode_Out_PP(通用推挽输出) 换算成32位的16进制是:0x0000 0010 3)引脚的速率是GPIO_Sp
[单片机]
基于<font color='red'>STM32</font>单片机流水灯控制中的GPIO_Init()函数解析
再造STM32---第十八部分:DMA—直接存储区访问
本章参考资料:《STM32F4xx 中文参考手册》 DMA 控制器章节。 学习本章时,配合《STM32F4xx 中文参考手册》 DMA 控制器章节一起阅读,效果会更佳,特别是涉及到寄存器说明的部分。本章内容专业名称较多,内容丰富也较难理解,但非常有必要细读研究。 特别说明,本章内容是以 STM32F42xxx 系列资源讲解。 18.1 DMA简介: DMA: Data Memory Access,直接存储器访问 DMA1: P- M, M- P, DMA2: P- M, M- P, M- M 1-通道+流 2-仲裁器 3-FIFO 4-存储器接口 5-外设接口 6-编程接口 流: 是数据传输的一条链路,每个DMA控制器有8
[单片机]
再造STM32---第十八部分:<font color='red'>DMA</font>—直接存储区访问
STM32 USART使用DMA设置
1、外设时钟初始化 首先初始化需要用到的外围设备设备的时钟,需要初始化的始终有USART RX DMA使用的DMA1、USART1、USART1使用的GPIO、AFIO(如果USART的管脚需要Remap则需要打开否则不用); /* DMA clock enable (USART RX using dma1) */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* USART clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* Enable GPIO cloc
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved