[stm32f407]stm32f407DMA使用

1.DMA实现内存UART数据转运:

1.初始串口:Serial_Init(); 

2.初始DMA:DMA_init();

3.开启串口DMA通道:USART_DMACmd();

4.检测标志位,清楚标志位;

5.DMA_Cmd;

#include "stm32f4xx.h"                  // Device header
#include "serial.h"
#include "delay.h"


#define BUFFER_SIZE 10


uint8_t buffer[BUFFER_SIZE]={97,97,97,97,97,97,97,97,97,97};//97对应ascci为a

void DMA_init();
void DMA_Enable();

uint16_t k=0;

int main(void)
{
    uint32_t DelayCnt=0;
    Serial_Init();  
    DMA_init();   
    /*给内存数组赋值*/
    buffer[0]='0';buffer[1]='1';buffer[2]='2';//buffer[3]='3';buffer[4]='4';buffer[5]='5';
    //buffer[6]='6';buffer[7]='7';buffer[8]='8';buffer[9]='9';
    
    USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);

    printf("buffer[3]=%d\r\n",buffer[3]);
    printf("success");

       /*等待DMA传输完成*/
       if(DMA_GetFlagStatus(DMA1_Stream6,DMA_FLAG_TCIF6)==SET)
      {
          //清楚DMA
          DMA_ClearFlag(DMA1_Stream6,DMA_FLAG_TCIF6);          
      }    

      DMA_Enable();//DMA_Cmd(DMA1_Stream6,ENABLE);
    
  while (1)
  {
     

      
  }
}

void DMA_init(){//Memory_to_Periph

    DMA_InitTypeDef DMA_InitStructure;       
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE) ;

    DMA_StructInit(&DMA_InitStructure);    		
                                  
    DMA_InitStructure.DMA_DIR=DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t)buffer;//因为地址是32位,写为uint32_t
    DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)(&USART2->DR);    
    DMA_InitStructure.DMA_Channel=DMA_Channel_4 ;
    DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//尝试不同模式
    DMA_InitStructure.DMA_BufferSize=BUFFER_SIZE;  
    
    DMA_InitStructure.DMA_Priority=DMA_Priority_High;
    DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//ENABLE
    DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//ENABLE
    DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte ;
    DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single ;

    DMA_Init(DMA1_Stream6,&DMA_InitStructure); 
        
}
    
void DMA_Enable(){    
    //与DMA_BufferSize一个含义,优先级更高,如使用则以DMA_BufferSize为准
    //DMA_SetCurrDataCounter(DMA1_Stream6,BUFFER_SIZE);
    DMA_Cmd(DMA1_Stream6,ENABLE);
}

DMA_BufferSize为需要转运的数据量,如DMA_BufferSize=3则仅转运前三个数据“012”,DMA_BufferSize=7则转运“012aaaa”;

函数DMA_SetCurrDataCounter()与DMA_BufferSize起一个作用,可不用

DMA_Mode_Circular如何停止?

为什么内存到内存实际上是Flash到SRAM?

DMA实现内存到内存数据转运:

#include "stm32f4xx.h"                  // Device header
#include "serial.h"
#include "delay.h"


#define BUFFER_SIZE 10


uint8_t SendArray[BUFFER_SIZE]={97,97,97,97,97,97,97,97,97,97};
uint8_t ReceiveArray[BUFFER_SIZE]={0};

void DMA_init();
void DMA_Enable();

uint16_t k=0;

int main(void)
{

    Serial_Init();  
    DMA_init();   
    /*给内存数组赋值*/
    SendArray[1]='0';SendArray[1]='1';SendArray[2]='2';SendArray[3]='3';SendArray[4]='4';SendArray[5]='5';
    SendArray[6]='6';SendArray[7]='7';SendArray[8]='8';SendArray[9]='9';
    
    //USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);


    printf("success");

       /*等待DMA传输完成*/
//       if(DMA_GetFlagStatus(DMA2_Stream4,DMA_FLAG_TCIF4)==SET)
//      {
//          //DMA
//          DMA_ClearFlag(DMA2_Stream4,DMA_FLAG_TCIF4);
//          
//      }    

      DMA_Enable();

      for(uint8_t k=0;k<BUFFER_SIZE;k++){
          printf("ReceiveArray[%d]=%d\r\n",k,ReceiveArray[k]);
      }
      
  while (1)
  {
     
      Delay_ms(5000);

      
  }
}

void DMA_init(){//Memory_to_Periph

    DMA_InitTypeDef DMA_InitStructure;       
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE) ;

    DMA_StructInit(&DMA_InitStructure);    		
                                  
    DMA_InitStructure.DMA_DIR=DMA_DIR_MemoryToMemory;
    DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)SendArray;     
    DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t)(ReceiveArray);//因为地址是32位,写为uint32_t
    DMA_InitStructure.DMA_Channel=DMA_Channel_4 ;
    DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//尝试不同模式
    DMA_InitStructure.DMA_BufferSize=BUFFER_SIZE;  
    //DMA_SxCR   NDTR USART_DR
    DMA_InitStructure.DMA_Priority=DMA_Priority_High;
    
    DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//ENABLE
    DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Enable ;//ENABLE
    DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte ;
    
    DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single ;

    DMA_Init(DMA2_Stream4,&DMA_InitStructure); 
        
}
    
void DMA_Enable(){    
    //与DMA_BufferSize一个含义,优先级更高,如使用则以DMA_BufferSize为准
    //DMA_SetCurrDataCounter(DMA1_Stream6,BUFFER_SIZE);
    DMA_Cmd(DMA2_Stream4,ENABLE);
}




注意,起始地址对应DMA_PeripheralBaseAddr;

缺少DMA_ITConfig();

3.实现USART到内存数据转运:

main.c

#include "stm32f4xx.h"                  // Device header
#include "delay.h"



#include "serial.h"
#include <stdio.h>



#define BUFF_SIZE 10
void DMA_USART_to_RAM();
uint8_t RxData;
uint8_t RxFlag;
uint8_t RxBuf[BUFF_SIZE]={0};
void DMA_USART_ENABLE();
int main(){
    Serial_Init();
    DMA_USART_to_RAM();
    
    printf("success\r\n");
   
    while(1){
            if(RxFlag==1){                
                printf("into interrupt\r\n");                
                DMA_USART_ENABLE();                
                printf("RxData=%d\r\n",RxData);
                printf("USART_ReceiveData(USART2)=%d\r\n",USART_ReceiveData(USART2));
                while(DMA_GetFlagStatus(DMA1_Stream5,DMA_FLAG_TCIF5)==RESET);

                for(uint16_t k=0;k<BUFF_SIZE;k++){
                printf("RxBuf[%d]=%d\r\n",k,RxBuf[k]);                
                }
                RxFlag=0;
            }
    } 
}

void DMA_USART_to_RAM(){
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);    
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_BufferSize=BUFF_SIZE; 
    DMA_InitStructure.DMA_Channel=DMA_Channel_4;
    
    DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_Memory0BaseAddr=(uint32_t)&RxBuf;  
    DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)&USART2->DR;     
    DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;//深入理解
    DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;//FIFO缓冲区填满之后,DMA进行转运
    
    DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;    
    DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
    
    DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;    
    DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;  
    DMA_InitStructure.DMA_Priority=DMA_Priority_High;    
    DMA_Init(DMA1_Stream5,&DMA_InitStructure);
    DMA_ITConfig(DMA1_Stream5,DMA_IT_TC,ENABLE);
}

void DMA_USART_ENABLE(){
    USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
    DMA_Cmd(DMA1_Stream5,ENABLE);
}
void USART2_IRQHandler(){
	if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET){
		RxData=USART_ReceiveData(USART2);
        RxFlag=1;
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);        
		}
}



serial.c:

#include "stm32f4xx.h"                  // Device header

#include <stdio.h> 
#include <stdarg.h>
 


void Serial_Init(void)
{	
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    // 配置PA9引脚为USART1的TX功能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // 配置PA10引脚为USART1的RX功能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // 将PA9和PA10引脚连接到USART1的TX和RX功能上
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART2, &USART_InitStructure);    
    USART_ITConfig(USART2,USART_IT_RXNE|USART_IT_IDLE,ENABLE);
	/*接收需要中断*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel= USART2_IRQn ;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE ;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1 ;
	NVIC_Init(&NVIC_InitStructure);	
    // 使能USART2
    USART_Cmd(USART2, ENABLE);
}
int fputc(int ch,FILE *f){
	USART_SendData(USART2,ch);
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);                
	return ch;
}

DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;所以,USART接收DMA_BufferSize数量数据之后,执行DMA转运;

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值