STM32-DMA

DMA: Data memory Access, 直接存储器访问。 可以把数据从一个地方传输到另一个地方,而且不占用CPU。 DMA1: 7个通道,M->M,P->M,M->P. DMA2: 5个通道 , M->M,P->M,M->P. (存在大容量、互联型(f105/f107)产品中)

系统结构
DMA1请求映射
DMA2请求映射

多个DMA同时请求:

1.软件阶段,DMA_CCRx DMA通道配置寄存器PL--->设置通道优先级

2.硬件阶段,通道编号小的优先级大,DMA1优先级大于DMA2的优先级

下面用两种传输方向来介绍DMA结构体

1.M - > M: Flash to SRAM, 内部FLASH (CODE)的数据传输到内部的SRAM(变量)

2.M -> P : SRAM to 串口 + LED,延时DMA传输数据不需要占用CPU

注:当源端数据宽度和目标数据宽度不一样时可参考中文参考手册DMA模块数据对齐表

M->M:

1.在FLASH中定义好要传输的数据,在SRAM中定义好接收FLASH数据的变量

2.初始化DMA结构体

3.编写比较函数

4.main函数应用

dma.c:

cs 复制代码
#include "stm32f10x.h"
#include "dma.h"



//const 关键字 把数组Buffer定义为常量类型,表示数据存储在内部的flash中
const uint32_t SRC_Buffer[BUFFER_SIZE] = {

    0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
	0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
	0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,
	0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40

};
//定义DMA传输的目标存储器,存储在内部SRAM
 uint32_t DST_BUFFER[BUFFER_SIZE];

void DMA_MTM_Init(void)
{


    DMA_InitTypeDef  DMA_InitStruct;
	
    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1,ENABLE);

    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)SRC_Buffer;//外设地址
    DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)DST_BUFFER;//存储器地址
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;//传输方向,外设作为源
	
	DMA_InitStruct.DMA_BufferSize = BUFFER_SIZE;//传输数目
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Enable;//外设地址增量模式
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器地址增量模式
	
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//外设数据宽度
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;//存储器数据宽度
	
	DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;//模式选择,循环发送还是只发送一次
	DMA_InitStruct.DMA_Priority = DMA_Priority_High;//通道优先级
	DMA_InitStruct.DMA_M2M = DMA_M2M_Enable;//存储器到存储器模式使能
	
    DMA_Init(DMA1_Channel6,&DMA_InitStruct);
    DMA_ClearFlag( DMA1_FLAG_TC6);//清除发送完成标志位
    DMA_Cmd(DMA1_Channel6,ENABLE);
	
}
uint8_t Buffercmp(const uint32_t* pBffer1, uint32_t *pBffer2,uint32_t BfferLength)
{

    while(BfferLength--)//数据长度递减
		{
		    if(*pBffer1 != *pBffer2)//判断两个数据源是否相等
				{
				
				   return 0;          //对应数据源不相等返回0
				
				}
				pBffer1++;     //递增两个数据源地址指针
				pBffer2++;
		
		
		}
   
    return 1;    //完成判断并且对应数据源相等返回1
}

dma.h

cs 复制代码
#ifndef _DMA_H_
#define _DMA_H_
#include "stm32f10x.h"

void DMA_MTM_Init(void);
uint8_t Buffercmp(const uint32_t* pBffer1, uint32_t *pBffer2,uint32_t BfferLength);
void USART_DMA_Init(void);

#define BUFFER_SIZE 16
#define USART_DR_ADDR (USART1_BASE+0X04)
#define SEND_SIZE  500

#endif

main.c

cs 复制代码
int main(void)
{
  uint8_t status = 0;
  extern const uint32_t SRC_Buffer[BUFFER_SIZE] ;
  extern  uint32_t DST_BUFFER[BUFFER_SIZE];
	
	LED_Init();
    DMA_MTM_Init();
	
	status = Buffercmp(SRC_Buffer,DST_BUFFER,BUFFER_SIZE);
	
	if(status == 0)
	{
	
	  GPIO_ResetBits(GPIOA,  GPIO_Pin_1);//如果返回值为0,则传输失败PA1引脚输出低电平led亮
	}
	else
	{
	 
	  GPIO_SetBits(GPIOA,  GPIO_Pin_1);//相反
	}
	 while(1)
	{
     


	}
}
M->P:

dma.c:

cs 复制代码
uint8_t SendBuffer[SEND_SIZE];
void USART_DMA_Init(void)
{

    DMA_InitTypeDef  DMA_InitStruct;
	
    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1,ENABLE);

    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)USART_DR_ADDR;//外设地址(串口1数据寄存器的地址)
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)SendBuffer;//存储器地址
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;//传输方向,外设作为传输目标
	
	DMA_InitStruct.DMA_BufferSize = SEND_SIZE;//传输数目
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器地址增量模式
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址增量模式关闭
	
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度
	DMA_InitStruct.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;//存储器数据宽度
	
	DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;//模式选择只发送一次
	DMA_InitStruct.DMA_Priority = DMA_Priority_High;//通道优先级
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;//存储器到存储器模式关闭
	
	DMA_Init(DMA1_Channel4,&DMA_InitStruct);//初始化DMA1通道4结构体
    DMA_ClearFlag( DMA1_FLAG_TC4);//清除发送完成标志位
    DMA_Cmd(DMA1_Channel4,ENABLE);//DMA1通道4使能

}

dma.h

cs 复制代码
#ifndef _DMA_H_
#define _DMA_H_
#include "stm32f10x.h"

void DMA_MTM_Init(void);
uint8_t Buffercmp(const uint32_t* pBffer1, uint32_t *pBffer2,uint32_t BfferLength);
void USART_DMA_Init(void);

#define BUFFER_SIZE 16
#define USART_DR_ADDR (USART1_BASE+0X04)
#define SEND_SIZE  500

#endif

usart.c

cs 复制代码
       // USART1初始化
       void  myusart_init(void)
       {
            GPIO_InitTypeDef GPIOInitStruct;
            USART_InitTypeDef USARTInitStruct;
	        NVIC_InitTypeDef NVIC_Initstruct;
	
  	        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	    
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE);
	
			 //A9 TX
		    GPIOInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
		    GPIOInitStruct.GPIO_Speed = GPIO_Speed_10MHz;
		    GPIOInitStruct.GPIO_Pin = GPIO_Pin_9;
		    GPIO_Init(GPIOA,&GPIOInitStruct);
			
	       //A10 RX
	
			GPIOInitStruct.GPIO_Mode = GPIO_Mode_IPU;
			GPIOInitStruct.GPIO_Pin = GPIO_Pin_10;
			GPIO_Init(GPIOA,&GPIOInitStruct);
	
	
	
			USARTInitStruct.USART_BaudRate = 115200;
			USARTInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
			USARTInitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
			USARTInitStruct.USART_Parity = USART_Parity_No;
			USARTInitStruct.USART_StopBits = USART_StopBits_1;
			USARTInitStruct.USART_WordLength = USART_WordLength_8b;
			USART_Init(USART1,&USARTInitStruct);
			USART_Cmd(USART1,ENABLE);
            USART_ITConfig(USART1,  USART_IT_RXNE,ENABLE);
			
			NVIC_Initstruct.NVIC_IRQChannel = USART1_IRQn;
			NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 0;
			NVIC_Initstruct.NVIC_IRQChannelSubPriority = 0;
			NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE;
			NVIC_Init(&NVIC_Initstruct);

          }

main.c

cs 复制代码
int main(void)
{

	uint16_t i=0;
	extern uint8_t SendBuffer[SEND_SIZE];
	
	for(i=0;i<SEND_SIZE;i++)
	{
	
	   SendBuffer[i] = '0';
	
	
	}
	myusart_init();
	USART_DMA_Init();
    USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
	
	
	
	 while(1)
	{
     


	}
}
传输完成:
相关推荐
猫猫的小茶馆21 分钟前
【PCB工艺】软件是如何控制硬件的发展过程
开发语言·stm32·单片机·嵌入式硬件·mcu·51单片机·pcb工艺
多多*4 小时前
Java设计模式 简单工厂模式 工厂方法模式 抽象工厂模式 模版工厂模式 模式对比
java·linux·运维·服务器·stm32·单片机·嵌入式硬件
Android洋芋5 小时前
C语言深度解析:从零到系统级开发的完整指南
c语言·开发语言·stm32·条件语句·循环语句·结构体与联合体·指针基础
小麦嵌入式11 小时前
Linux驱动开发实战(九):Linux内核pinctrl_map详解与优势分析
linux·c语言·汇编·驱动开发·stm32·嵌入式硬件·硬件工程
傍晚冰川15 小时前
【STM32】最后一刷-江科大Flash闪存-学习笔记
笔记·科技·stm32·单片机·嵌入式硬件·学习·实时音视频
电子艾号哲16 小时前
STM32单片机入门学习——第1-2节: [1-1、2]课程和STM32简介
stm32·单片机·学习
触角010100011 天前
MPU6050模块详解:从原理到STM32驱动指南(上) | 零基础入门STM32第八十九步
驱动开发·stm32·单片机·嵌入式硬件·物联网
不被定义的~wolf1 天前
【STM32】系统滴答计时器systick
stm32·单片机·嵌入式硬件
傍晚冰川2 天前
【STM32】WDG看门狗(学习笔记)
c语言·笔记·科技·stm32·单片机·嵌入式硬件·学习