STM32F0 中 ADC 多通道轉換結果相同的問題
阿新 • • 發佈:2018-10-17
type 前段時間 isp external res lin version splay flag
前言
前段時間調試 STM32F030 的 ADC,在多通道轉換時遇到了奇怪的問題,使用官方的例程和庫函數連續轉換多個 ADC 通道,得到的幾個通道的結果是一樣的,解決辦法參考了 關於STM32F0系列多路ADC單獨采樣數據相同問題的處理,在此表示感謝。
記錄
在官方庫的例程 ADC_BasicExample 中的初始化和轉換方法如下
ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* GPIOC Periph clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE); /* ADC1 Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* Configure ADC Channel11 as analog input */ #ifdef USE_STM320518_EVAL GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ; #else GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; #endif /* USE_STM320518_EVAL */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure); /* ADCs DeInit */ ADC_DeInit(ADC1); /* Initialize ADC structure */ ADC_StructInit(&ADC_InitStructure); /* Configure the ADC1 in continuous mode with a resolution equal to 12 bits */ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward; ADC_Init(ADC1, &ADC_InitStructure); /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */ #ifdef USE_STM320518_EVAL ADC_ChannelConfig(ADC1, ADC_Channel_11 , ADC_SampleTime_239_5Cycles); #else ADC_ChannelConfig(ADC1, ADC_Channel_10 , ADC_SampleTime_239_5Cycles); #endif /* USE_STM320518_EVAL */ /* ADC Calibration */ ADC_GetCalibrationFactor(ADC1); /* Enable the ADC peripheral */ ADC_Cmd(ADC1, ENABLE); /* Wait the ADRDY flag */ while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)); /* ADC1 regular Software Start Conv */ ADC_StartOfConversion(ADC1); while (1) { /* Test EOC flag */ while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); /* Get ADC1 converted data */ ADC1ConvertedValue =ADC_GetConversionValue(ADC1); /* Compute the voltage */ ADC1ConvertedVoltage = (ADC1ConvertedValue *3300)/0xFFF; /* Display converted data on the LCD */ Display(); }
可見庫函數中切換通道是使用 ADC_ChannelConfig(ADC1, ADC_Channel_11, ADC_SampleTime_239_5Cycles),在庫函數中 ADC_ChannelConfig 函數源碼如下
void ADC_ChannelConfig(ADC_TypeDef* ADCx, uint32_t ADC_Channel, uint32_t ADC_SampleTime) { uint32_t tmpreg = 0; /* Check the parameters */ assert_param(IS_ADC_ALL_PERIPH(ADCx)); assert_param(IS_ADC_CHANNEL(ADC_Channel)); assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime)); /* Configure the ADC Channel */ ADCx->CHSELR |= (uint32_t)ADC_Channel; /* Clear the Sampling time Selection bits */ tmpreg &= ~ADC_SMPR1_SMPR; /* Set the ADC Sampling Time register */ tmpreg |= (uint32_t)ADC_SampleTime; /* Configure the ADC Sample time register */ ADCx->SMPR = tmpreg ; }
其中 ADCx->CHSELR |= (uint32_t)ADC_Channel 對寄存器賦值使用了“|”,這會造成下一次循環轉換時仍然轉換最高位通道
解決辦法是,在每次調用 ADC_ChannelConfig 之後,再對寄存器寫入
uint16_t ADC_Get_Result(uint32_t ch) { ADC_ChannelConfig(ADC1, ch, ADC_SampleTime_239_5Cycles); ADC1->CHSELR = ch; while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)){}; ADC_StartOfConversion(ADC1); while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET){}; return ADC_GetConversionValue(ADC1)&0x00000fff; }
STM32F0 中 ADC 多通道轉換結果相同的問題