help - most simple way for ADC - STM32F103
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-11-25 2:22 AM
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 adviseint16_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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-11-25 6:43 AM
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.Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-11-25 10:00 AM
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-11-25 10:28 AM
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));
}
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-11-25 11:03 AM
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-11-25 12:05 PM
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);
Up vote any posts that you find helpful, it shows what's working..
