cancel
Showing results for 
Search instead for 
Did you mean: 

help - most simple way for ADC - STM32F103

mehmet.karakaya
Associate III
Posted on November 25, 2013 at 11:22

hello dear forum,

( STM32F103 ) I am trying to measure 5 analog signal with most simple way I am taking10 consecutiveADC result and take their avarage however I have trouble with ADC , the measurements are wrong sometimes the ADC ''get stuck'' with a fake value sometimes it measures wrong value btw I am measuring 5 analog channels, I showed 2 of them below beouse the idea is the same have a look at my code and please advise

int16_t averhold[5][20]; 
void
ADCinit(
void
){ 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 
GPIO_Init(GPIOC, &GPIO_InitStructure); 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 
GPIO_Init(GPIOA, &GPIO_InitStructure); 
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
ADC_InitStructure.ADC_ScanConvMode = DISABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
ADC_InitStructure.ADC_NbrOfChannel = 1; 
ADC_Init(ADC1, &ADC_InitStructure); 
/* ADC1 regular channels configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_28Cycles5); 
/* Regular discontinuous mode channel number configuration */
ADC_DiscModeChannelCountConfig(ADC1, 1); 
/* Enable regular discontinuous mode */
ADC_DiscModeCmd(ADC1, ENABLE); 
/* Enable ADC1 external trigger conversion */
ADC_ExternalTrigConvCmd(ADC1, ENABLE); 
/* Set injected sequencer length */
/* ADC1 injected channel configuration */
/* ADC1 injected external trigger configuration */
/* Enable ADC1 injected external trigger conversion */
/* Enable JEOC interupt */
// ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); 
/* Enable ADC1 DMA */
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE); 
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1); 
/* Check the end of ADC1 reset calibration register */
while
(ADC_GetResetCalibrationStatus(ADC1)); 
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1); 
/* Check the end of ADC1 calibration */
while
(ADC_GetCalibrationStatus(ADC1)); 
} 

here is the measurement block

void
GetADCRes(
void
){ 
int16_t *RAMptr ; 
int8_t avi;
//avi2; 
int32_t avertotal=0; 
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_28Cycles5); 
for
(avi=0;avi<10;avi++){ 
ADC_SoftwareStartConvCmd(ADC1, ENABLE); 
while
(ADC_GetSoftwareStartConvStatus(ADC1)); 
Delay(20); 
RAMptr= &averhold[0][avi]; 
*RAMptr= ADC_GetConversionValue(ADC1); 
} 
avertotal=0; 
for
(avi=0; avi<10; avi++) avertotal += averhold[0][avi]; 
RAMptr=&RAM[PARAMETERS + 100*2 ]; 
*RAMptr= avertotal / 10; 
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_28Cycles5); 
for
(avi=0;avi<10;avi++){ 
ADC_SoftwareStartConvCmd(ADC1, ENABLE); 
while
(ADC_GetSoftwareStartConvStatus(ADC1)); 
Delay(20); 
RAMptr= &averhold[1][avi]; 
*RAMptr= ADC_GetConversionValue(ADC1); 
} 
avertotal=0; 
for
(avi=0; avi<10; avi++) avertotal += averhold[1][avi]; 
RAMptr=&RAM[PARAMETERS + 101*2 ]; 
*RAMptr= avertotal / 10; 
}

what I want to ask is , is this measurement code correct ?

ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_28Cycles5); 
for
(avi=0;avi<10;avi++){ 
ADC_SoftwareStartConvCmd(ADC1, ENABLE); 
while
(ADC_GetSoftwareStartConvStatus(ADC1)); 
Delay(20); 
RAMptr= &averhold[1][avi]; 
*RAMptr= ADC_GetConversionValue(ADC1); 
} 

this rank , should it be different for every channel ? I am taking it ''1'' for every channel

void
ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)

thank you #stm32
5 REPLIES 5
Posted on November 25, 2013 at 15:43

Both the C and implementation are pretty awful.

Why the use pointers, delays, and not using EOC status? There are far more elegant ways to solve this problem.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mehmet.karakaya
Associate III
Posted on November 25, 2013 at 19:00

hello thanks for the answer

the STM32F10x peripheral library gives only DMA or ext_trigger examples for ADC

does anyone have a working example for software_conversion_start

for 2 or more channels ADC measurement ?

thank you

Posted on November 25, 2013 at 19:28

That's likely because the simple/elegant way to do what you're attempting is to use DMA, and compute the average for all channels/samples in the DMA's TC interrupt?

I'm still confused by why you are using pointers to access an array element. Something like this would seem to be a clearer interpretation of the library functions. (F4 here but should port)

uint16_t ADCReadValue(uint8_t Channel)
{
ADC_RegularChannelConfig(ADC1, Channel, 1, ADC_SampleTime_28Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
return(ADC_GetConversionValue(ADC1));
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mehmet.karakaya
Associate III
Posted on November 25, 2013 at 20:03

now I know its not smart to access array element with pointer

however this code is written when I was new to STM and C

and I learned C after 40  age :) 

maybe thats why

originally I measured only single ADC channel with this code and it worked fine

thats why I didnot changed it since then

now for another project I need to measure 5 channels and I got into trouble

thank you for the advice and I assume

you say OK to my initialization routine

Posted on November 25, 2013 at 21:05

Honestly this looks to be extraneous, and you're not using an external trigger.

/* Regular discontinuous mode channel number configuration */
ADC_DiscModeChannelCountConfig(ADC1, 1);
/* Enable regular discontinuous mode */
ADC_DiscModeCmd(ADC1, ENABLE);
/* Enable ADC1 external trigger conversion */ 
ADC_ExternalTrigConvCmd(ADC1, ENABLE);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..