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 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> Stm32之DMA直接内存读取(2021-07-30) -> 正文阅读

[嵌入式]Stm32之DMA直接内存读取(2021-07-30)

Stm32之DMA直接内存读取

1.DMA简介:

  • DMA*(Direct Memory Access controller)*:可用于为CPU减负,可以将内存中的数据与外设中的数据进行搬运(无法进行计算操作,单纯的搬运),而在此期间内CPU可以去处理其他事物。

    (说白了,就是一个搬运工)

  • 特性简介如下:(摘自原子的数据书册)

    • Stm32有两个DMA控制器,DMA1(7个通道),DMA2(5个通道);

    • 有三种传输单位宽度可选:字节(8位)、半字(16位)、全字(32位);

    • 通道间有四种优先级可调配:很高、高、中等和低;

    • 有三种中断/事件标志:DMA 半传输(传输一半了),DMA 传输完成和 DMA 传输出错;

    • 有三种传输方向:M2M(内存到内存);M2P(内存到外设);P2M(外设到内存);

    • 闪存、SRAM、外设的SRAM、APB1 APB2 和 AHB 外设均可作为访问的源和目标。

    • 可编程的数据传输数目:最大为 65536

2.DMA的外设对应通道:

? DMA每个外设所对应的通道,都是确定好的,默认的优先级及各外设对应的通道如下:

在这里插入图片描述

在这里插入图片描述

3.相关寄存器:

此处DMA1与DMA2控制的寄存器的地址是分开的,因此只介绍DMA1;DMA2的所有寄存器应该于DMA1类似,均排列在DMA1后(即先全部是DMA1的寄存器,再是DMA2的寄存器);

  • DMA interrupt status register (DMA_ISR):中断标志位:每个通道各4个,共占28位[27:0]

    • TEIFx: Transfer Error Interr Flag传输错误标志位
    • HIIFx: Half Transfer Interr Flag传输过半标志位
    • TCIFx: Transfer Complete Interr Flag传输完成标志位
    • GIFx: Global Interr Flag全局中断标志位(只要上述中断有一个发生,该位就置一)
  • DMA interrupt flag clear register (DMA_IFCR):中断标志清除位:一样占28位[27:0];用于与ISR一一对应清除标志;

  • DMA channel x configuration register (DMA_CCRx) (x = 1…7):

    各个通道的通道控制寄存器:(每个寄存器占15位[14:0])

    • MEM2MEM[14]:是否使能内存到内存的搬运;

    • PL[13:12]:priority level优先级配置;00-低;01-中;10-高;11-最高;

    • MSIZE[11:10]: Memory size传输内存单位大小;00-8位;01-16位;10-32位;11-保留;

    • PSIZE[9:8]: Peripheral size传输到外设单位大小;00-8位;01-16位;10-32位;11-保留;

    • MINC[7]: Memory increment mode,内存地址是否自增;

    • PINC[6]: Peripheral increment mode,外设地址石否自增;

    • CIRC[5]: Circular mode,是否使能循环传输;

    • DIR[4]: Data transfer direction,传输方向:0-P2M;1-M2P;

    • [3:0] TEIE(Transfer error interrupt enable)和HTIE( Half transfer interrupt enable)和TCIE(Transfer complete interrupt enable)三个中断标志的使能位;

    • EN[0]:该通道的使能位。

  • DMA channel x number of data register (DMA_CNDTRx) (x = 1…7):该寄存器的值是通道传输的数据长度,占16位,所以最大值位65535;

  • DMA channel x peripheral address register (DMA_CPARx) (x = 1…7), 32位寄存器,用来存放要传输的外设的地址;

  • DMA channel x memory address register (DMA_CMARx) (x = 1…7),32位寄存器,用来存放要传输的内存的地址;

4.库函数操作:

  • 使能DMA的时钟:RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMAx(1/2), ENABLE)

  • 初始化要开启的通道参数:

    DMA_Init(DMA_Channel_TypeDef DMAy_Channelx, DMA_InitTypeDef DMA_InitStruct)** 要求的参数除了通道几外,还有一个结构体用于设置传输时的具体参数:

    typedef struct
    {
     uint32_t DMA_PeripheralBaseAddr;//外设基地址
    uint32_t DMA_MemoryBaseAddr; //外设基地址
     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; //单次(Normal)还是循环(Circle)
     uint32_t DMA_Priority; //优先级
     uint32_t DMA_M2M; //是否开启内存传到内存
    }DMA_InitTypeDef;
    
  • 对于外设,均要使能该外设:DMA_Cmd(DMA_Channelx, ENABLE);

  • 注意:使用DMA传输时,在对应外设中,要将外设中的DMA传输开启;

    如: ADC_DMACmd(ADC3,ENABLE);//使能ADC3到DMA的转换

  • 两个常用的库函数:

    FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)
    //在 DMA 传输过程中,我们要查询 DMA 传输通道的状态,参数为DMAy_FLAG_TCx;DMAy的x通道
    
    uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx)
    //是获取当前剩余数据量大小,参数同样是DMAy的通道x
    
    

5.关于地址:

  • 如果是内存的地址,我们需要使用”&“符号将地址传入即可,

    • 如果是数组,则之间将数组名传入即可(而且,数组变量CPU不会优化,会从内存中取值);

    • 但如果仅仅是单个变量,需要在声明变量是加上关键字” volatile “以表明,cpu不会优化该变量,每次均会去内存中取值,这样我们读到的值才是DMA每次更新的值
      (有点像51中的 code 关键字,将声明的变量存于rom(不可再修改,类似C的consist)中,而默认51是存在寄存器,也就是ram中的)

  • 对于各种外设的地址,有两种方式获取:

    • 一是,通过查表得出外设的基地址,再加上对应寄存器的偏移量即可。

      各外设的基地址汇总如下(出自数据手册):

    在这里插入图片描述

    • 二是利用ST封好的库函数中的地址宏进行加减计算;

      (第一种方法算出来的地址也建议自定义成宏,提高可读性和代码效率)

      在顶层头文件stm32f103x.h中有定义外设的及地址,如下:

      #define FLASH_BASE            ((uint32_t)0x08000000) /*!< FLASH base address in the alias region */
      #define SRAM_BASE             ((uint32_t)0x20000000) /*!< SRAM base address in the alias region */
      #define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
      
      #define SRAM_BB_BASE          ((uint32_t)0x22000000) /*!< SRAM base address in the bit-band region */
      #define PERIPH_BB_BASE        ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */
      
      #define FSMC_R_BASE           ((uint32_t)0xA0000000) /*!< FSMC registers base address */
      
      /*!< Peripheral memory map */
      #define APB1PERIPH_BASE       PERIPH_BASE
      #define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
      #define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)
      
      #define TIM2_BASE             (APB1PERIPH_BASE + 0x0000)
      #define TIM3_BASE             (APB1PERIPH_BASE + 0x0400)
      #define TIM4_BASE             (APB1PERIPH_BASE + 0x0800)
      #define TIM5_BASE             (APB1PERIPH_BASE + 0x0C00)
      #define TIM6_BASE             (APB1PERIPH_BASE + 0x1000)
      #define TIM7_BASE             (APB1PERIPH_BASE + 0x1400)
      #define TIM12_BASE            (APB1PERIPH_BASE + 0x1800)
      #define TIM13_BASE            (APB1PERIPH_BASE + 0x1C00)
      #define TIM14_BASE            (APB1PERIPH_BASE + 0x2000)
      #define RTC_BASE              (APB1PERIPH_BASE + 0x2800)
      #define WWDG_BASE             (APB1PERIPH_BASE + 0x2C00)
      #define IWDG_BASE             (APB1PERIPH_BASE + 0x3000)
      #define SPI2_BASE             (APB1PERIPH_BASE + 0x3800)
      #define SPI3_BASE             (APB1PERIPH_BASE + 0x3C00)
      #define USART2_BASE           (APB1PERIPH_BASE + 0x4400)
      #define USART3_BASE           (APB1PERIPH_BASE + 0x4800)
      #define UART4_BASE            (APB1PERIPH_BASE + 0x4C00)
      #define UART5_BASE            (APB1PERIPH_BASE + 0x5000)
      #define I2C1_BASE             (APB1PERIPH_BASE + 0x5400)
      #define I2C2_BASE             (APB1PERIPH_BASE + 0x5800)
      #define CAN1_BASE             (APB1PERIPH_BASE + 0x6400)
      #define CAN2_BASE             (APB1PERIPH_BASE + 0x6800)
      #define BKP_BASE              (APB1PERIPH_BASE + 0x6C00)
      #define PWR_BASE              (APB1PERIPH_BASE + 0x7000)
      #define DAC_BASE              (APB1PERIPH_BASE + 0x7400)
      #define CEC_BASE              (APB1PERIPH_BASE + 0x7800)
      
      #define AFIO_BASE             (APB2PERIPH_BASE + 0x0000)
      #define EXTI_BASE             (APB2PERIPH_BASE + 0x0400)
      #define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
      #define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
      #define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
      #define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
      #define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
      #define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
      #define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)
      #define ADC1_BASE             (APB2PERIPH_BASE + 0x2400)
      #define ADC2_BASE             (APB2PERIPH_BASE + 0x2800)
      #define TIM1_BASE             (APB2PERIPH_BASE + 0x2C00)
      #define SPI1_BASE             (APB2PERIPH_BASE + 0x3000)
      #define TIM8_BASE             (APB2PERIPH_BASE + 0x3400)
      #define USART1_BASE           (APB2PERIPH_BASE + 0x3800)
      #define ADC3_BASE             (APB2PERIPH_BASE + 0x3C00)
      #define TIM15_BASE            (APB2PERIPH_BASE + 0x4000)
      #define TIM16_BASE            (APB2PERIPH_BASE + 0x4400)
      #define TIM17_BASE            (APB2PERIPH_BASE + 0x4800)
      #define TIM9_BASE             (APB2PERIPH_BASE + 0x4C00)
      #define TIM10_BASE            (APB2PERIPH_BASE + 0x5000)
      #define TIM11_BASE            (APB2PERIPH_BASE + 0x5400)
      
      #define SDIO_BASE             (PERIPH_BASE + 0x18000)
      
      #define DMA1_BASE             (AHBPERIPH_BASE + 0x0000)
      #define DMA1_Channel1_BASE    (AHBPERIPH_BASE + 0x0008)
      #define DMA1_Channel2_BASE    (AHBPERIPH_BASE + 0x001C)
      #define DMA1_Channel3_BASE    (AHBPERIPH_BASE + 0x0030)
      #define DMA1_Channel4_BASE    (AHBPERIPH_BASE + 0x0044)
      #define DMA1_Channel5_BASE    (AHBPERIPH_BASE + 0x0058)
      #define DMA1_Channel6_BASE    (AHBPERIPH_BASE + 0x006C)
      #define DMA1_Channel7_BASE    (AHBPERIPH_BASE + 0x0080)
      #define DMA2_BASE             (AHBPERIPH_BASE + 0x0400)
      #define DMA2_Channel1_BASE    (AHBPERIPH_BASE + 0x0408)
      #define DMA2_Channel2_BASE    (AHBPERIPH_BASE + 0x041C)
      #define DMA2_Channel3_BASE    (AHBPERIPH_BASE + 0x0430)
      #define DMA2_Channel4_BASE    (AHBPERIPH_BASE + 0x0444)
      #define DMA2_Channel5_BASE    (AHBPERIPH_BASE + 0x0458)
      #define RCC_BASE              (AHBPERIPH_BASE + 0x1000)
      #define CRC_BASE              (AHBPERIPH_BASE + 0x3000)
      
      #define FLASH_R_BASE          (AHBPERIPH_BASE + 0x2000) /*!< Flash registers base address */
      #define OB_BASE               ((uint32_t)0x1FFFF800)    /*!< Flash Option Bytes base address */
      
      #define ETH_BASE              (AHBPERIPH_BASE + 0x8000)
      #define ETH_MAC_BASE          (ETH_BASE)
      #define ETH_MMC_BASE          (ETH_BASE + 0x0100)
      #define ETH_PTP_BASE          (ETH_BASE + 0x0700)
      #define ETH_DMA_BASE          (ETH_BASE + 0x1000)
      
      #define FSMC_Bank1_R_BASE     (FSMC_R_BASE + 0x0000) /*!< FSMC Bank1 registers base address */
      #define FSMC_Bank1E_R_BASE    (FSMC_R_BASE + 0x0104) /*!< FSMC Bank1E registers base address */
      #define FSMC_Bank2_R_BASE     (FSMC_R_BASE + 0x0060) /*!< FSMC Bank2 registers base address */
      #define FSMC_Bank3_R_BASE     (FSMC_R_BASE + 0x0080) /*!< FSMC Bank3 registers base address */
      #define FSMC_Bank4_R_BASE     (FSMC_R_BASE + 0x00A0) /*!< FSMC Bank4 registers base address */
      
      #define DBGMCU_BASE          ((uint32_t)0xE0042000) /*!< Debug MCU registers base address */
      

      使用时加上对应寄存器的偏移量即可:如下:

      #define ADC3_DR_Address (ADC3_BASE+0x4C)//DR偏移量0x4c
      
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:48:39  更:2021-07-31 16:49:13 
 
开发: 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/25 18:29:12-

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