STM32F4四路ADC取樣問題探討
阿新 • • 發佈:2019-01-11
1.ADC配置
1.1模式確定
主從模式,選擇主ADC1模式帶動從ADC2模式
對應程式碼段:
/* 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
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;
這裡相關配置就可以結束了,需注意的是,計算取樣時需要定義陣列,陣列型別也有明確要求。這裡附上程式配置相關檔案。