STM32F4四路ADC采样问题探讨

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/klaus_x/article/details/78822115

1.ADC配置

1.1模式确定

主从模式,选择主ADC1模式带动从ADC2模式
ADC模式
交替模式
对应代码段:

/* Enable DMA request after last transfer (Multi-ADC mode)  */
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);

1.2 时钟初始化ADC

ADC时钟挂在APB2上,这里程序配置为168MHz

RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);

RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2,ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2,DISABLE);

1.3 引脚选择和初始化

1.3.1 引脚

这里的ADC是加DMA的,需要根据DMA和ADC相关默认引脚来选择
简化来说 PC0–ADC通道10,PC1–ADC通道11…
选定相应引脚

1.3.2 初始化配置

ADC_Init(ADC2, &ADC_InitStructure);
/* ADC2 regular channel5 configuration ****************/
ADC_RegularChannelConfig(ADC2,ADC_Channel_13,1,
ADC_SampleTime_15Cycles);		//PC3
/* ADC1 regular channel5 configuration ************/
ADC_RegularChannelConfig(ADC2, ADC_Channel_11, 2, ADC_SampleTime_15Cycles);		//PA3

ADC_Init(ADC1, &ADC_InitStructure); 

/* ADC1 regular channel5 configuration ****************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_15Cycles);		//PC2
/* ADC1 regular channel5 configuration ******************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_15Cycles);		//PA5
...
ADC_Cmd(ADC1, ENABLE)
ADC_Cmd(ADC2, ENABLE);

2.DMA配置

2.1初始化

确定数据流,这里F4系列的开发板有3个ADC
DMA2

2.2程序配置

/* DMA2 Stream0 channel2 configuration */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;  
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)aADCConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = ADC_BUF_SIZE;
DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;         
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream0, ENABLE);

3.滤波平均

3.1一般滤波方法

这里尝试过其他一些滤波方法,加权滤波,中值滤波,滑动滤波方法,在大数据量下,排序消耗时间和占用资源都比较不好,经测试,一般滤波方法比较好。

u32 adc_filter(u32 cnt,u32 adc_num_value){
	u8 i;
	u32 adc_min=0,adc_max=0;
	u32 adc_sum=0,adc_ave=0;
	for(i=0;i<cnt;i++){
		adc_sum += adc_num_value;
		adc_min=adc_num_value;
		adc_max=adc_num_value;
		
		if(adc_num_value<=adc_min)
			adc_min=adc_num_value;
		if(adc_num_value>=adc_max)
			adc_max=adc_num_value;
	}
	adc_sum -= (adc_max+adc_min);	
	adc_ave=adc_sum/(cnt-2);
	adc_sum=0;
	return adc_ave;
}

3.2 采样计算求值

根据之前规定的组合依次可计算出各采样值,这里优化了浮点计算方法

u8 j,k;
u32 adc_getvalue[4];
memset(&adc_getvalue,0,sizeof(adc_getvalue));
for(j=0;j<40;j++)
{
	for(k=0;k<4;k++)
	adc_getvalue[k] += adc_filter(8,aADCConvertedValue[k]);
}//PC3--[1] PC1--[3] PC2--[0] PA5--[2]
voltage1_calculate=	(float)adc_getvalue[0]*33/(400*4096);
voltage2_calculate=	(float)adc_getvalue[1]*33/(400*4096);
current1_calculate=	(float)adc_getvalue[2]*33/(400*4096);
current2_calculate=	(float)adc_getvalue[3]*33/(400*4096);
	
memset(&adc_getvalue,0,sizeof(adc_getvalue));
	
//减少线差
adc_voltage1=voltage1_calculate;
adc_voltage2=voltage2_calculate;
adc_current1=current1_calculate;
adc_current2=current2_calculate;			

这里相关配置就可以结束了,需注意的是,计算采样时需要定义数组,数组类型也有明确要求。这里附上程序配置相关文件

猜你喜欢

转载自blog.csdn.net/klaus_x/article/details/78822115