DAM能快速的搬运数据并且不影响程序的运行,处理外设数据比str函数要好,str相关函数还是占时间的
DMA外设通道选择:具体看手册 M-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);
}
调试结果:
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);
}
调试:
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);
}
调试:
要是不循环去中断里面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也是同理的;加油加油!!!