求解求解STM32F207ZET6 ADC转换误差问题,
我在新项目中第一次用STM32F207ZET6,使用了ADC1,ADC3两个独立的ADC,使用中发现无关的代码回影响ADC采样的数据精度,好像和编译后代码量有关。困扰好长时间了,不知道哪里出问题啊,谁能指点一下。
ADC1采样12个通道,连续循环采样,开DMA自动读取AD数据到数据RAM。
void ADC_Configuration(void)
{
u8 i;
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOC,ENABLE);
// RCC_ADCCLKConfig(RCC_PCLK2_Div6);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_InitStructure.DMA_Channel=DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_ADDRESS;//ADC1½Ó¿Ú¼Ä´æÆ÷Ê×µØÖ· ÍâÉèµØÖ·
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1_Value;//ADCConvertedValue;//ADC½á¹ûµØÖ·
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//dma´«Êä·½Ïòµ¥Ïò
DMA_InitStructure.DMA_BufferSize = 120;//120;// 13*10 //ÉèÖÃDMAÔÚ´«Êäʱ»º³åÇøµÄ³¤¶È word
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//ÉèÖÃDMAµÄÍâÉèµÝÔöģʽ
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//ÉèÖÃDMAµÄÄÚ´æµÝÔöģʽ
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//ÍâÉèÊý¾Ý×Ö³¤
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//ÄÚ´æÊý¾Ý×Ö³¤
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//ÉèÖÃDMAµÄ´«Êäģʽ£ºÁ¬Ðø²»¶ÏµÄÑ»·Ä£Ê½
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//ÉèÖÃDMAµÄÓÅÏȼ¶±ð
DMA_InitStructure.DMA_FIFOMode= DMA_FIFOMode_Disable; //DMA_FIFOMode_Enable;//0617
DMA_InitStructure.DMA_FIFOThreshold= DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst= DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst= DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream4, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream4, ENABLE);//Enable DMA1 channel1
// ADC1 configuration ------------------------------------------------------
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;// =/8
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; //Á½¸ö²ÉÑù¼ä¸ô20¸öÖÜÆÚ
ADC_CommonInit(&ADC_CommonInitStructure);
//----------------------------------
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode =ENABLE;//DISABLE; //
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 12;
ADC_Init(ADC1, &ADC_InitStructure);
LED3_turn();//(其他地方程序完全不变)使用这条指令和不使用这条指令,
对我的AD转换出的结果差别有0.5V(检测的输出电压53.0v变53.5v),
这是一条控制LED开关指令,原来放在中断里,也有影响,换其他一条指令也一样,
比如一条ADC_EOCOnEachRegularChannelCmd(ADC1, DISABLE);而且,
在KEIL 设置编译代码优化级别不同也会出现上面检测电压不偏差问题,
真不知道怎么回事,ST 的FAE真难请啊!
// ADC1 regular channel configuration
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);//²ÉÑùÖÜÆÚ
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 3, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 4, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 5, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 6, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 7, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 8, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 9, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 10, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 11, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 12, ADC_SampleTime_144Cycles);//ADC_SampleTime_56Cycles);
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);// Enable ADC1
ADC_Cmd(ADC1, ENABLE);// Enable ADC1
ADC_SoftwareStartConv(ADC1);// Start ADC1 Software Conversion
}
uint32_t AnalogFilter(uint16_t ADCDataTab[], uint16_t nChannel)
{
/* ¶¨ÒåÁÙʱ±äÁ¿*/
uint8_t i;
uint32_t averagevalue=0;
uint32_t maxvalue=0;
uint32_t minvalue=0xFFFFFFFF;
#define maxchn 12 //ͨµÀÊý
#define maxcou 10 //»º´æÊý
for (i=0;i<maxcou;i++) //166us*100=16.67ms
{
averagevalue += *(ADCDataTab+nChannel+i*maxchn);
if(*(ADCDataTab+nChannel+i*maxchn)>maxvalue) //Ñ°ÕÒ×î´óÖµ
{
maxvalue=*(ADCDataTab+nChannel+i*maxchn);
}
if(*(ADCDataTab+nChannel+i*maxchn)<minvalue) //Ñ°ÕÒ×îСÖ
{
minvalue=*(ADCDataTab+nChannel+i*maxchn);
}
}
averagevalue=(averagevalue-maxvalue-minvalue)>>3; //ȡƽ¾ùÖµ
return averagevalue; //·µ»ØÂ˲¨Öµ
}
void GetSystemVoltage(void)
{
u32 TempData;
u16 bb;
TempData = AnalogFilter(ADC1_Value,0);
TempData = TempData *6270/4096;
outvol =(u16)TempData;
}
|
|