stm32学习笔记——DMA

邮差的信 提交于 2019-11-30 18:17:31

stm32学习笔记——DMA

目的:用DMA发送数据到USART1并同时点亮LED灯,熟悉DMA配置过程

配置文件:#include "stm32f10x_dma.h"

          #include "stm32f10x_gpio.h"

          #include "stm32f10x_rcc.h"

          #include "stm32f10x_usart.h"

结构体定义:

typedef struct

{

  uint32_t DMA_PeripheralBaseAddr; //DMA传输目标地址

 

  uint32_t DMA_MemoryBaseAddr; //DAM传输源地址

    

  uint32_t DMA_DIR;     //DMA传输方向

           

  uint32_t DMA_BufferSize; //DMA传输大小

                                          

 uint32_t DMA_PeripheralInc;     //外设是否开启地址自增 

 

  uint32_t DMA_MemoryInc;          //内存是否开启地址自增/

 

  uint32_t DMA_PeripheralDataSize;//外设数据单元

 

  uint32_t DMA_MemoryDataSize;     //内存数据单元,与前者须一致

 

  uint32_t DMA_Mode;              //DMA模式,可循环,也可不循环

 

  uint32_t DMA_Priority;           //DMA优先级,多个DMA申请出现时需考虑

 

  uint32_t DMA_M2M;                //内存到内存传输

}DMA_InitTypeDef;

 

其中DMA_DIR有宏定义如下:

#define DMA_DIR_PeripheralDST              ((uint32_t)0x00000010)外设为目标

#define DMA_DIR_PeripheralSRC              ((uint32_t)0x00000000)内存为目标

 

DMA_PeripheralInc;有宏定义如下:

#define DMA_PeripheralInc_Enable           ((uint32_t)0x00000040)开启自增

#define DMA_PeripheralInc_Disable          ((uint32_t)0x00000000)关闭自增

 

DMA_MemoryInc有宏定义如下:

#define DMA_MemoryInc_Enable               ((uint32_t)0x00000080)开启自增

#define DMA_MemoryInc_Disable              ((uint32_t)0x00000000)关闭自增

 

DMA_PeripheralDataSize有宏定义如下:

#define DMA_PeripheralDataSize_Byte        ((uint32_t)0x00000000)字节

#define DMA_PeripheralDataSize_HalfWord    ((uint32_t)0x00000100)半字

#define DMA_PeripheralDataSize_Word        ((uint32_t)0x00000200)

 

DMA_MemoryDataSize有宏定义如下:

#define DMA_MemoryDataSize_Byte            ((uint32_t)0x00000000)

#define DMA_MemoryDataSize_HalfWord        ((uint32_t)0x00000400)

#define DMA_MemoryDataSize_Word            ((uint32_t)0x00000800)

 

DMA_Priority有宏定义如下:

#define DMA_Priority_VeryHigh              ((uint32_t)0x00003000)

#define DMA_Priority_High                  ((uint32_t)0x00002000)

#define DMA_Priority_Medium                ((uint32_t)0x00001000)

#define DMA_Priority_Low                   ((uint32_t)0x00000000)

 

DMA_Mode有宏定义如下:

#define DMA_Mode_Circular                  ((uint32_t)0x00000020)

#define DMA_Mode_Normal                    ((uint32_t)0x00000000)

 

DMA_M2M有宏定义如下:

#define DMA_M2M_Enable                     ((uint32_t)0x00004000)

#define DMA_M2M_Disable                    ((uint32_t)0x00000000)

 

注意,DMA使用重点就在于该结构体的参数配置,需认真掌握。

 

库函数:

DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)初始化DMA函数,参数:DMA通道号码,DMA结构体DMA_InitTypeDef。其中通道号注意需要查阅参考手册,不同外设对应着指定的通道号。

 

DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState)DMA使能函数,参数:DMA通道号,使能or不使能

 

USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState)USARTDMA发出申请的函数,参数:USART号,发送or接收申请,使能or不使能。其中有宏定义如下:

#define USART_DMAReq_Tx                      ((uint16_t)0x0080)发送申请

#define USART_DMAReq_Rx                      ((uint16_t)0x0040)接收申请

此函数是在USART中设定的,并不是DMA中设定的。 stm32f10x_usart.c

 

程序代码比较简单,有两个核心,第一个是配置USART,参阅USART,第二个就是配置DMA,其核心又是配置其初始化结构体。先只须分析DMA配置即可。

 

void USART1_DMA_Config(void)

{

DMA_InitTypeDef DMA_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//开启DMA1时钟

 

DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base//设置目标地址   

 

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;//设置源地址

 

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //外设为目标

DMA_InitStructure.DMA_BufferSize = SENDBUFF_SIZE;//大小为5000,自己可写宏定义定义SENDBUFF_SIZE

 

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不自增

 

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址自增

 

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//单位字节

 

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  //单位字节

 

//DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //循环发送

 

DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;  //优先级为中

 

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//禁止内存到内存

   

DMA_Init(DMA1_Channel4, &DMA_InitStructure);     初始化,注意USART1对应的为DMA1的通道4

DMA_Cmd (DMA1_Channel4,ENABLE); //DMA使能

//DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);  

}

注意:1、目标地址怎么算,传输的是USART1的数据寄存器地址,用USART1的基地址加上数 据寄存器地址的偏移量可得

2、源地址怎么算,这里我们开的是一个数组,数组名本身就是基地址,可直接作为参 数写入,无须加指针

3、内存地址为什么自增,因为在读取数组的时候,我们需要把数组一位一位的读取出来,指针要从基地址开始不断后移然后读数,自然需要地址自增。

4、外设地址为什么不自增,外设地址为USART1的数据寄存器,其地址固定不变的,受到数据后USART1将会自动发送到移位寄存器发送出去,所以不自增。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!