洋桃开发板笔记(七 ) 初步了解DMA——直接存储器访问


初步了解DMA——直接存储器访问

杜洋工作室 www.DoYoung.net

洋桃电子 www.DoYoung.net/YT

  • 在此声明一下所有代码均为杜洋工作室的不允许复制,转发以及在商业上的行为等,本人只是在此程序上进行理解和注释。

上一次的笔记是在洋桃开发板上进行Flash闪存的使用,主要配合其他外设。对Flash的基本了解有兴趣可以去看看:
https://blog.csdn.net/qq_40546576/article/details/99695256
本次主要讲的是了解DMA。由于本次特殊,需要截取部分图片进行讲解,可能造成了观看不适,请大家谅解!谢谢。


DMA主要是可以直接访问数据,不需要通过CPU。可以外设和内存之间相互访问,也可以内存与内存之间访问。
很不幸STM32不是只有一个DMA,居然有2个DMA,分别为DMA1与DMA2。
接下来我们介绍STM32F10xxx参考手册

了解《STM32F10xxx参考手册》

麻烦大家多看看《STM32F10xxx参考手册》,这个样子会直接查看手册,大家就会对不同的芯片都会游刃有余。
洋桃开发板笔记(七 ) 初步了解DMA——直接存储器访问_第1张图片
我用的是洋桃开发板,里面是STM32F103C8T6的Flash闪存为32K字节,属于小容量的。

官方介绍

洋桃开发板笔记(七 ) 初步了解DMA——直接存储器访问_第2张图片

主要特征

洋桃开发板笔记(七 ) 初步了解DMA——直接存储器访问_第3张图片
洋桃开发板笔记(七 ) 初步了解DMA——直接存储器访问_第4张图片
STM32的DMA1有7个通道,DMA2有5个通道,相信大家看了上面的介绍因该了解这个通道个数,呢么每个通道也有各自的用处的,下面展示DMA1每个通道可以干什么(接收哪些请求)
洋桃开发板笔记(七 ) 初步了解DMA——直接存储器访问_第5张图片
呢么DMA2的每个通道又有什么用处呢,下面展示DMA2每个通道接收哪些请求
洋桃开发板笔记(七 ) 初步了解DMA——直接存储器访问_第6张图片

DMA的固件库使用

接下来这个才是我们真正要用的必须掌握,前面均可以了解。
我们需要选择的DMA配置
官方固件库内定义的(stm32f10x_dmah)

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. */
  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 */
  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 */
  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 */
  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 */
  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;
/***********************************************************************************************************************/
//上面为官方的英文翻译一下(个人理解):

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;               /*模式,传输为一次,还是循环传输 */
  uint32_t DMA_Priority;           /*优先级*/
  uint32_t DMA_M2M;         /*是否为存储器传输到存储器*/
}DMA_InitTypeDef;
//注:M2M的表达和P2P表达方法一样P是点,2的英语发音为to,也就是点对点,我们这里M2M则为内存对内存

接下来我们单独拿出洋桃家的代码进行分析,他家入门100步视频没有专门介绍DMA部分,但是提及了和解释ADC中的DMA相关的代码。我们截取部分在ADC中的DMA初始化程序,大家可以了解一下。可能不适合大家的代码需求,不能直接复制使用!!

void ADC_DMA_Init(void){ //DMA初始化设置
	DMA_InitTypeDef DMA_InitStructure;   //定义DMA初始化结构体
	DMA_DeInit(DMA1_Channel1);    //复位DMA通道1
	DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //定义DMA通道外设基地址=ADC1_DR_Address
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_DMA_IN; //!!!定义DMA通道ADC数据存储器(其他函数可直接读此变量即是ADC值)
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//指定外设为源地址
	DMA_InitStructure.DMA_BufferSize = 2;//!!!定义DMA缓冲区大小(根据ADC采集通道数量修改)
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//当前外设寄存器地址不变
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//!!! 当前存储器地址:Disable不变,Enable递增(用于多通道采集)
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度16位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //定义存储器数据宽度16位
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA通道操作模式位环形缓冲模式
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA通道优先级高
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//禁止DMA通道存储器到存储器传输
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA通道1
	DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA通道1
}

上面程序还需要一个开启时钟程序,程序可以放在初始化程序中也可以放在其他程序,但是一定是在整个初始化过程中开启。
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA时钟
洋桃家放在GPIO初始化中,而秉火家放在DMA初始化中,其实一样的,但不可以缺少!!!


下面我们了解stm32的ADC的使用,还有DAC的。
最后用ADC和DMA做一些小东西


参考来源:

  • Google搜寻引擎等等
  • 杜洋工作室 www.DoYoung.net
  • 洋桃电子 www.DoYoung.net/YT
  • STM32库开发实战指南 基于STM32F103(第二版)
  • 《stm32f1xx 参考手册》

你可能感兴趣的:(自学STM32)