2018-08-02 01:27 AM
I'm using STM32F030F4, when use 48MHz HSI, everything seems ok, and the internal voltage reference is read as 1.24v. But when reduce the HCLK from 48MHz to 1MHz, the ADC seems work abnormal, the internal voltage is read as 1.41V. I tried different HCLK 48MHz, 8MHz, 4MHz, 2MHz, the internal voltage are all read about 1.22~1.24V, when 1MHz, it's 1.41V. Paste the ADC_config() code below. Does anyone ever have this problem?
=============================================
static void DAC_Config(void)
{
DAC_InitTypeDef DAC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* Configure PA.04 (DAC_OUT1) in analog mode -------------------------*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable DAC clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
/* DAC channel1 Configuration */
DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
/* DAC Channel1 Init */
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
/* Enable DAC Channel1 */
DAC_Cmd(DAC_Channel_1, ENABLE);
}
static void ADC_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* ADC1 and TIM1 Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* Configure ADC Channels as analog input */
GPIO_InitStructure.GPIO_Pin = PTC_PIN;//PA5, ADC_IN5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(PTC_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = PWR_PIN;//PA6, ADC_IN6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(PWR_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SELFTEST_PIN;//PA0, ADC_IN0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(SELFTEST_PORT, &GPIO_InitStructure);
/* ADC1 DeInit */
ADC_DeInit(ADC1);
/* Initialize ADC structure */
ADC_StructInit(&ADC_InitStructure);
/* Configure the ADC1 in continous mode withe 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_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC4;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
/* Convert the ADC1 Channel11 and channel10 with 239.5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_55_5Cycles);
ADC_ChannelConfig(ADC1, ADC_Channel_5 , ADC_SampleTime_55_5Cycles);
ADC_ChannelConfig(ADC1, ADC_Channel_6 , ADC_SampleTime_55_5Cycles);
/* Convert the ADC1 temperature sensor with 55.5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor , ADC_SampleTime_55_5Cycles);
ADC_TempSensorCmd(ENABLE);
/* Convert the ADC1 Vref with 55.5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_55_5Cycles);
ADC_VrefintCmd(ENABLE);
/* Convert the ADC1 Vbat with 55.5 Cycles as sampling time
ADC_ChannelConfig(ADC1, ADC_Channel_Vbat , ADC_SampleTime_28_5Cycles);
ADC_VbatCmd(ENABLE);*/
/* ADC Calibration */
ADC_GetCalibrationFactor(ADC1);
/* ADC DMA request in circular mode */
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_OneShot);
/* DMA1 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
/* DMA1 Channel1 Config--for ADC */
//DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RegularConvData_Tab;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 5;
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_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//DMA interrupt
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);//interrupt when transfer complete
/* Enable DMA1 channel1 IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* DMA1 Channel1 enable */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* Enable ADC_DMA */
ADC_DMACmd(ADC1, ENABLE);
/* 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);
}
2018-08-02 05:59 AM
Where in ADC_InitStructure do you set the clock-mode? It might be ADCCLK (HSI14 asynchronous) or PCLK/2 or PCLK/4.
The ADC may be clocked at any rate between 0.6 and 14 MHz (ref: Data sheet 6.3.16 12-bit ADC Characteristics).
If APB is 48 MHz, PCLK/4 will be within spec.
If APB is 1 MHz, PCLK/2 and PCLK/4 are out-of-spec so you might expect errors in conversion result.
Hope this helps,
Danish
2018-08-05 03:16 AM
Thanks Danish, change the ADC clock source can solve the problem! But some different situation from document you use. I didn't explicit set the ADC clock source, but seems the default setting is 14MHz clock. When I explicit set clock source to 14MHz, the problem still there. But when change clock source to PCLK/2 or PCLK/4, the problem solved! The internal voltage read OK(1.24V) and seems other channel is also correct reading. The PCLK is still 1MHz. I don't know why...I'm referring DM00091010 document, and didn't see the ADC clock limitation. Which document are you using?
=============works well under PCLK 1MHz=================
static void ADC_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* ADC1 and TIM1 Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* Configure ADC Channels as analog input */
GPIO_InitStructure.GPIO_Pin = PTC_PIN;//PA5, ADC_IN5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(PTC_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = PWR_PIN;//PA6, ADC_IN6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(PWR_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SELFTEST_PIN;//PA0, ADC_IN0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(SELFTEST_PORT, &GPIO_InitStructure);
/* ADC1 DeInit */
ADC_DeInit(ADC1);
/* ADC clock mode*/
ADC_ClockModeConfig(ADC1, ADC_ClockMode_SynClkDiv2);
/* Initialize ADC structure */
ADC_StructInit(&ADC_InitStructure);
/* Configure the ADC1 in continous mode withe 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_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC4;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC1, &ADC_InitStructure);
/* Convert the ADC1 Channel11 and channel10 with 239.5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_55_5Cycles);
ADC_ChannelConfig(ADC1, ADC_Channel_5 , ADC_SampleTime_55_5Cycles);
ADC_ChannelConfig(ADC1, ADC_Channel_6 , ADC_SampleTime_55_5Cycles);
/* Convert the ADC1 temperature sensor with 55.5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor , ADC_SampleTime_55_5Cycles);
ADC_TempSensorCmd(ENABLE);
/* Convert the ADC1 Vref with 55.5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_55_5Cycles);
ADC_VrefintCmd(ENABLE);
/* Convert the ADC1 Vbat with 55.5 Cycles as sampling time
ADC_ChannelConfig(ADC1, ADC_Channel_Vbat , ADC_SampleTime_28_5Cycles);
ADC_VbatCmd(ENABLE);*/
/* ADC Calibration */
ADC_GetCalibrationFactor(ADC1);
/* ADC DMA request in circular mode */
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_OneShot);
/* DMA1 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
/* DMA1 Channel1 Config--for ADC */
//DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RegularConvData_Tab;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 5;
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_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//DMA interrupt
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);//interrupt when transfer complete
/* Enable DMA1 channel1 IRQ Channel */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* DMA1 Channel1 enable */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* Enable ADC_DMA */
ADC_DMACmd(ADC1, ENABLE);
/* 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);
}