简介
1.DMA的主要作用是提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无需CPU干预,数据可以通过DMA来快速的移动,这样就节省了CPU的资源来做其他的操作。
2.STM32F1中DMA控制器有两个,DMA1有7个通道,DMA2有5各通道。
3.每个通道专门用来管理来自一个或者多个外设存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。
最后讲一下对DMA的理解,DMA其实就相当于一个通道嘛,就是有时候我们要放一些数据,但是又不想占用CPU的资源,所以就可以通过DMA通道传到一些地址暂时存放着,我们需要的时候再来用。没有CPU的涉及,传输速度就非常的快嘛
下面是DMA+ADC的代码
#include "adc.h"
/******************************************
ADC初始化
******************************************/
GPIO_InitTypeDef GPIO_InitSt_ADC;
ADC_InitTypeDef ADC_InitSt;
ADC_CommonInitTypeDef ADC_CommonInitSt;
void BuckBoost_ADC_Init(void)
{
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div6);//72/6=14M
ADC_DeInit(ADC1);
/*ADC1_IO口初始化*/
GPIO_InitSt_ADC.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitSt_ADC.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitSt_ADC.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA,&GPIO_InitSt_ADC);
/*ADC2_IO口初始化*/
GPIO_InitSt_ADC.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_Init(GPIOA,&GPIO_InitSt_ADC);
GPIO_InitSt_ADC.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOB,&GPIO_InitSt_ADC);
/* Calibration procedure */
ADC_VoltageRegulatorCmd(ADC1,ENABLE);//ADC稳压器
delay_ms(10);
ADC_SelectCalibrationMode(ADC1,ADC_CalibrationMode_Single);//选择单通道校准模式
ADC_StartCalibration(ADC1);//开始选择的ADC校准过程
while(ADC_GetCalibrationStatus(ADC1));//校准结束
ADC_VoltageRegulatorCmd(ADC2,ENABLE);//ADC稳压器
delay_ms(10);
ADC_SelectCalibrationMode(ADC2,ADC_CalibrationMode_Single);//选择单通道校准模式
ADC_StartCalibration(ADC2);//开始选择的ADC校准过程
while(ADC_GetCalibrationStatus(ADC2));//校准结束
//ADC通用设置
ADC_CommonInitSt.ADC_Clock = ADC_Clock_AsynClkMode;
ADC_CommonInitSt.ADC_DMAAccessMode =ADC_DMAAccessMode_1;//
ADC_CommonInitSt.ADC_DMAMode = ADC_DMAMode_Circular;
ADC_CommonInitSt.ADC_Mode = ADC_Mode_RegSimul;//adc模式
ADC_CommonInitSt.ADC_TwoSamplingDelay = 10;
ADC_CommonInit(ADC1,&ADC_CommonInitSt);
//ADC初始化
ADC_InitSt.ADC_AutoInjMode = ADC_AutoInjec_Disable;//不使用自动转换
ADC_InitSt.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;//转换模式
ADC_InitSt.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitSt.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;//软件触发
ADC_InitSt.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;//无触发器
ADC_InitSt.ADC_NbrOfRegChannel = 5;
ADC_InitSt.ADC_OverrunMode = ADC_OverrunMode_Disable;//不使用溢出
ADC_InitSt.ADC_Resolution = ADC_Resolution_12b;//12位
ADC_Init(ADC1,&ADC_InitSt);
ADC_Init(ADC2,&ADC_InitSt);
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_2,2,ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_3,3,ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_4,4,ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC2,ADC_Channel_1,1,ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC2,ADC_Channel_2,2,ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC2,ADC_Channel_3,3,ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC2,ADC_Channel_4,4,ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC2,ADC_Channel_12,5,ADC_SampleTime_1Cycles5);
ADC_DMACmd(ADC1,ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_Cmd(ADC2,ENABLE);
while(!ADC_GetCommonFlagStatus(ADC1,ADC_FLAG_MSTRDY));
while(!ADC_GetCommonFlagStatus(ADC2,ADC_FLAG_SLVRDY));
}
/******************************************
ADC采样值电压换算
******************************************/
double ADC_Voltage_VaLue(u32 ADC_Valuex)
{
double Voltage_VaLue;
Voltage_VaLue=(double)(ADC_Valuex)*3.3/4095;
return Voltage_VaLue;
}
#include "dma.h"
/*DMA初始化*/
DMA_InitTypeDef DMA_InitSt_DM1;
void BuckBoost_DMA_Init(void)
{
DMA_DeInit(DMA1_Channel1);
DMA_InitSt_DM1.DMA_Mode = DMA_Mode_Circular;//模式
DMA_InitSt_DM1.DMA_Priority =DMA_Priority_High;//通道优先级
DMA_InitSt_DM1.DMA_PeripheralBaseAddr =(u32)&ADC1_2->CDR;//外设地址
DMA_InitSt_DM1.DMA_MemoryBaseAddr =(u32)ADC_Value;//存储器地址
DMA_InitSt_DM1.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//外设数据宽度
DMA_InitSt_DM1.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;//存储器数据宽度
DMA_InitSt_DM1.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不增加
DMA_InitSt_DM1.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器地址增
DMA_InitSt_DM1.DMA_BufferSize = ADC_BUFF_SIZE;//DMA缓冲大小
DMA_InitSt_DM1.DMA_DIR = DMA_DIR_PeripheralSRC;//从内存读数据
DMA_InitSt_DM1.DMA_M2M = DMA_M2M_Disable;//不启用存储器到存储器
DMA_Init(DMA1_Channel1,&DMA_InitSt_DM1);
DMA_Cmd(DMA1_Channel1, ENABLE); //使能 DMA1 所指示的通道
}
#ifdef adc_test
/******************************************
ADC测试程序
******************************************/
void ADC_Test_Program(void)
{
/******************************************
开始转换ADC
******************************************/
ADC_StartConversion(ADC1);
while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
DMA_ClearFlag(DMA1_FLAG_TC1);
ADC_I_IN=ADC_Voltage_VaLue(ADC_Value[0]&Low_Position);
ADC_V_IN=ADC_Voltage_VaLue(ADC_Value[1]&Low_Position);
ADC_I_OUT=ADC_Voltage_VaLue(ADC_Value[2]&Low_Position);
ADC_V_OUT=ADC_Voltage_VaLue(ADC_Value[3]&Low_Position);
temperature_1=ADC_Voltage_VaLue((ADC_Value[0]&High_Position)>>16);
temperature_2=ADC_Voltage_VaLue((ADC_Value[1]&High_Position)>>16);
temperature_3=ADC_Voltage_VaLue((ADC_Value[2]&High_Position)>>16);
temperature_4=ADC_Voltage_VaLue((ADC_Value[3]&High_Position)>>16);
temperature_5=ADC_Voltage_VaLue((ADC_Value[4]&High_Position)>>16);
printf("\r\n ");
printf("\r\n 输入电流:%.2fV 输入电压:%.2fV",ADC_I_IN,ADC_V_IN);
printf("\r\n 输出电流:%.2fV 输出电压:%.2fV",ADC_I_OUT,ADC_V_OUT);
printf("\r\n ");
printf("\r\n 温度检测1:%.2fV 温度检测2:%.2fV ",temperature_1,temperature_2);
printf("\r\n 温度检测3:%.2fV 温度检测4:%.2fV 温度检测5:%.2fV",temperature_3,temperature_4,temperature_5);
}
#endif