DAM能快速的搬运数据并且不影响程序的运行,处理外设数据比str函数要好,str相关函数还是占时间的

DMA外设通道选择:具体看手册 M-M那个通到都可以;

STM32DMA数据搬运 M-M M-P P-M三模式(串口)_串口

确实DMA只要确定好这3个配置就好了

1:外设地址 DMA_PeripheralBaseAddr

2:存储器地址 DMA_MemoryBaseAddr

3;方向 DIR

主要是方向,决定了数据是从外设到存储器还是存储器到外设

 //方向  D1存储器到外设 S0 外设到存储器  SRC     DTR

SRC就是DMA_PeripheralBaseAddr的数据去DMA_MemoryBaseAddr

DTR则相反;

要是M-M就要使能DMA_M2M这个配置,选择好反向;

其他配置决定外设/存储器的数据大小,地址是不是自增,是不是循环模式,M2M,优先级啥的,特别注意;如果不是循环模式,搬运数据前要在CMD一下DMA;配置了不循环执行,然后初始化的时候CMD了,当数据搬运完成了,就会停止,要在搬运数据前在CMD一次。

到外设就要开启相关的通道

 USART_DMACmd(USART1,USART_DMAReq_Tx, ENABLE);//使能串口的DMA

M-M配置方式:

1:开启DMA的时钟

2,初始化DMA(注意通道)

3.CMD(注意通道)

u8 a1[10]={1,2,3,4,5,6,7,8,9,10};

u8 a[10]={0};

void dma1_m_m_init(void)

{

DMA_InitTypeDef DMA1_InitStruct;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

DMA1_InitStruct.DMA_PeripheralBaseAddr=(u32)a;//w外设地址

DMA1_InitStruct.DMA_MemoryBaseAddr=(u32)a1;//存储器地址

DMA1_InitStruct.DMA_DIR=DMA_DIR_PeripheralDST ;  //发现 0:从外设读1:从存储器读  D1存储器到外设 S0 外设到存储器  

DMA1_InitStruct.DMA_BufferSize=10;//长度

DMA1_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Enable;//外设地址自增

DMA1_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器地址自增

DMA1_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;//外设数据宽度

DMA1_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;//存储器数据宽度

DMA1_InitStruct.DMA_Mode=DMA_Mode_Normal;//模式循环/不循环

DMA1_InitStruct.DMA_Priority=DMA_Priority_VeryHigh ;//优先级

DMA1_InitStruct.DMA_M2M=DMA_M2M_Enable ; //存储器到存储器搬运

DMA_Init(DMA1_Channel1,&DMA1_InitStruct);

DMA_Cmd(DMA1_Channel1, ENABLE);

}

调试结果:

STM32DMA数据搬运 M-M M-P P-M三模式(串口)_数据_02

2:M-P(串口发)

#define usart1_addr 0x40013804

我用USART->DR时候报错误了,就直接用地址了。。

void dma1_m_u1rx_init(void)

{

DMA_InitTypeDef DMA1_InitStruct;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

DMA1_InitStruct.DMA_PeripheralBaseAddr=usart1_addr;//w外设地址

DMA1_InitStruct.DMA_MemoryBaseAddr=(u32)a1;//存储器地址

DMA1_InitStruct.DMA_DIR=DMA_DIR_PeripheralSRC;  //发现 0:从外设读1:从存储器读  D1存储器到外设 S0 外设到存储器  

DMA1_InitStruct.DMA_BufferSize=10;//长度

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

DMA1_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器地址自增

DMA1_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;//外设数据宽度

DMA1_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;//存储器数据宽度

DMA1_InitStruct.DMA_Mode=DMA_Mode_Circular;//模式循环/不循环

DMA1_InitStruct.DMA_Priority=DMA_Priority_VeryHigh ;//优先级

DMA1_InitStruct.DMA_M2M=DMA_M2M_Disable ; //存储器到存储器搬运

DMA_Init(DMA1_Channel5,&DMA1_InitStruct);

USART_DMACmd(USART1,USART_DMAReq_Rx, ENABLE);//使能串口的DMA

DMA_Cmd(DMA1_Channel5, ENABLE);

}

调试:

STM32DMA数据搬运 M-M M-P P-M三模式(串口)_串口_03

3:P-M

这个可能要注意点循环模式了,如果开了循环模式,串口来数据了会直接搬运过去并且搬一个存储器地址加一个;要是没开循环,就要进入串口中断后在CMD一下。

开循环的:

void dma1_m_u1rx_init(void)

{

DMA_InitTypeDef DMA1_InitStruct;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

DMA1_InitStruct.DMA_PeripheralBaseAddr=usart1_addr;//w外设地址

DMA1_InitStruct.DMA_MemoryBaseAddr=(u32)a1;//存储器地址

DMA1_InitStruct.DMA_DIR=DMA_DIR_PeripheralSRC;  //发现 0:从外设读1:从存储器读  D1存储器到外设 S0 外设到存储器  

DMA1_InitStruct.DMA_BufferSize=10;//长度

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

DMA1_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器地址自增

DMA1_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;//外设数据宽度

DMA1_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;//存储器数据宽度

DMA1_InitStruct.DMA_Mode=DMA_Mode_Circular;//模式循环/不循环

DMA1_InitStruct.DMA_Priority=DMA_Priority_VeryHigh ;//优先级

DMA1_InitStruct.DMA_M2M=DMA_M2M_Disable ; //存储器到存储器搬运

DMA_Init(DMA1_Channel5,&DMA1_InitStruct);

USART_DMACmd(USART1,USART_DMAReq_Rx, ENABLE);//使能串口的DMA

DMA_Cmd(DMA1_Channel5, ENABLE);

}

调试:

STM32DMA数据搬运 M-M M-P P-M三模式(串口)_自增_04

要是不循环去中断里面CMD

void USART1_IRQHandler(void)

{

if(USART_GetITStatus(USART1,USART_IT_RXNE)==1)

{

// USART_DMACmd(USART1,USART_DMAReq_Rx, ENABLE);

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

 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==0);

 USART_ClearFlag(USART1,USART_FLAG_TXE);

}

USART_ClearFlag(USART1,USART_FLAG_RXNE);

}

到此结束;ADC也是同理的;加油加油!!!