2019-09-19 11:09 PM
Hello!
I'm trying to measure 3 ADC channels in DISCONT mode.
I use STM32Cube initialisation code for ADC initing.
/* ADC init function */
void MX_ADC_Init(void)
{
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
LL_ADC_InitTypeDef ADC_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC1);
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
/**ADC GPIO Configuration
PA6 ------> ADC_IN6
*/
GPIO_InitStruct.Pin = NTC_ADC_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(NTC_ADC_GPIO_Port, &GPIO_InitStruct);
/* ADC interrupt Init */
NVIC_SetPriority(ADC1_COMP_IRQn, 0);
NVIC_EnableIRQ(ADC1_COMP_IRQn);
/** Configure Regular Channel
*/
LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_6);
/** Configure Regular Channel
*/
LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_TEMPSENSOR);
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_TEMPSENSOR);
/** Configure Regular Channel
*/
LL_ADC_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_VREFINT);
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_VREFINT);
/** Common config
*/
ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_1RANK;
ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;
LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_160CYCLES_5);
LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE);
LL_ADC_REG_SetSequencerScanDirection(ADC1, LL_ADC_REG_SEQ_SCAN_DIR_FORWARD);
LL_ADC_SetCommonFrequencyMode(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_CLOCK_FREQ_MODE_LOW);
LL_ADC_DisableIT_EOC(ADC1);
LL_ADC_DisableIT_EOS(ADC1);
LL_ADC_EnableInternalRegulator(ADC1);
ADC_InitStruct.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV1;
ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
ADC_InitStruct.LowPowerMode = LL_ADC_LP_AUTOWAIT;
LL_ADC_Init(ADC1, &ADC_InitStruct);
}
After this I try to use
LL_ADC_REG_StartConversion(ADC1);
do {
do {} while(!LL_ADC_IsActiveFlag_EOC(ADC1));
results = LL_ADC_REG_ReadConversionData12(ADC1);
if (LL_ADC_IsActiveFlag_EOS(ADC1))
break;
LL_ADC_ClearFlag_EOC(ADC1);
} while(1);
but after first EOC flag ADSTART setted to low also and conversion stopping.
I expected that ADSTART will in high level during all sequence. (13.4.5 from reference manual)
What I do wrong?
2019-09-20 01:20 AM
But that's the very purpose of *discontinuous* mode, to break up the sequence of conversions to individual conversions. Read Discontinuous mode (DISCEN) subchapter.
JW
2019-09-20 02:13 AM
But how I can undestand, during all sequence ADSTART must be in HIGH level. And only EOC bit sets every channel conversion end. And only after all sequence complite ADC reset ADSTART bit.
In my case ADSTART resets after every channel conversion.
2019-09-20 05:06 AM
> But how I can undestand, during all sequence ADSTART must be in HIGH level. And only EOC bit sets every channel conversion end. And only after all sequence complite ADC reset ADSTART bit.
Yes, that's how it works if you *don't* set *discontinuous*.
JW
2019-09-22 09:02 PM
In this picture *not* continuous mode
2019-09-22 10:34 PM
Not CONTinuous is not DISContinuous.
The first is switched on by setting ADC_CFGR1.CONT bit, the second by ADC_CFGR1.DISCEN
This may be confusing, but there are in fact three "autorun" modes: normal, when none of these bits is set. when all conversions of a sequence are carried on automatically, stopping after the sequence, this is what you are after. Then you have Continuous, when after a completed sequence a new sequence is started automatically, there is no stop. Then you have Discontinuous, where there is a stop after each conversion in the sequence.
JW