cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Discovery ADC continuous conversion single channel

arlen
Associate II
Posted on August 19, 2016 at 18:56

Hi everybody, I've started to use the STM32F4 Discovery, now I'm trying to use the ADC as single channel in conitnuous mode without DMA, i doesn't work , is it posible to do it?

#include ''stm32f4xx.h''
#include ''stm32f4xx_rcc.h''
#include ''stm32f4xx_gpio.h''
#include ''stm32f4xx_adc.h''
//#include ''GPIO_STM32F4xx.h''
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
//DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
uint16_t ADCLect=0;
uint16_t Counter=0;
uint16_t Done=0;
volatile uint32_t msTicks; /* counts 1ms timeTicks */
FlagStatus Estado;
/*----------------------------------------------------------------------------
SysTick_Handler
*----------------------------------------------------------------------------*/
void SysTick_Handler(void) {
msTicks++;
}
/*----------------------------------------------------------------------------
delays number of tick Systicks (happens every 1 ms)
*----------------------------------------------------------------------------*/
void Delay (uint32_t dlyTicks) {
uint32_t curTicks;
curTicks = msTicks;
while ((msTicks - curTicks) < dlyTicks);
}
int main()
{
SystemCoreClockUpdate();
if (SysTick_Config(SystemCoreClock / 1000)) { /* SysTick 1 msec interrupts */
while (1); /* Capture error */
}
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* Configure PA1 in analog mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ADC Common configuration *************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 regular channel 12 configuration ************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//ENABLE;//DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_EOCOnEachRegularChannelCmd(ADC1,ENABLE);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_3Cycles);
ADC_ContinuousModeCmd(ADC1,ENABLE); // to make sure the CONT is set
/* Enable ADC1 **************************************************************/
ADC_Cmd(ADC1, ENABLE);
ADC_SoftwareStartConv(ADC1);
while (1)
{
//ADC_SoftwareStartConv(ADC1);
Estado = ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC);
if(Estado){
Done=1;
ADCLect = ADC_GetConversionValue(ADC1);
//ADC_ClearFlag(ADC1,ADC_FLAG_EOC); // to clear the flags events.
}
Delay(100);
}
return 0;
}

when I use the ADC in mode discontinuous using the code below works fine:

ADC_SoftwareStartConv(ADC1);
ADCLect = ADC_GetConversionValue(ADC1);
ADC_ClearFlag(ADC1,ADC_FLAG_EOC);

I hope somebody can help me #adc #continuous-conversion
7 REPLIES 7
Posted on August 19, 2016 at 21:09

Pick something longer than 3 cycles, the ADC is likely overflowing because you aren't servicing it quickly enough, check the status register when it fails...

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
arlen
Associate II
Posted on August 19, 2016 at 21:52

Hi clivel1,

thanks for your answer, I've tested with all options:

#define ADC_SampleTime_3Cycles ((uint8_t)0x00)
#define ADC_SampleTime_15Cycles ((uint8_t)0x01)
#define ADC_SampleTime_28Cycles ((uint8_t)0x02)
#define ADC_SampleTime_56Cycles ((uint8_t)0x03)
#define ADC_SampleTime_84Cycles ((uint8_t)0x04)
#define ADC_SampleTime_112Cycles ((uint8_t)0x05)
#define ADC_SampleTime_144Cycles ((uint8_t)0x06)
#define ADC_SampleTime_480Cycles ((uint8_t)0x07)

in the code I attached , it gives just one conversion, and if i delete the delay it gives two conversions with any of sample options, then

ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC);

alwasy gives '0' (T T) By the by, anyone know where can i find the datasheet of each module of the uC such as ADC, UART, etc? where i could see each register ... I can't find them i hope you can continue or someone else could help me thanks
Posted on August 19, 2016 at 22:19

Are you sitting in the debugger looking at this, or counting them another way? Suggest you toggle a GPIO and scope that, or review the ADC status in this condition.

What you are looking for is the

http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf

.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
arlen
Associate II
Posted on August 19, 2016 at 22:55

Hi again,

I use UART1 to check.

thanks

while (1)
{ 

Estado = ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC); 
if(Estado){
ADCLect = ADC_GetConversionValue(ADC1);

sprintf(texto,''ReadADC: %d ReadADC: %d \n\r'',ADCConvertedValue,ADCLect);
USART_puts(USART1,texto);
}

pls see picture attached

________________

Attachments :

Conversions.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hzog&d=%2Fa%2F0X0000000bPz%2FiLO1jtliZbFQUrFnT6Y4IV12iwpFqKNldyPhPOsKSNM&asPdf=false
Posted on August 20, 2016 at 01:43

Ok, but the USART output is going to take 20 ms (figure 1000 characters per second)

Suggest you enable one of the LEDs and toggle it every 1000 loops. Or a non-blocking output to a USART?

while (1)
{ 
Estado = ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC); 
if(Estado)
{
static int i = 0;
ADCLect = ADC_GetConversionValue(ADC1);
if ((i++ > 1000) && (USART_GetFlagStatus(USART1, USART_FLAG_TXE) != RESET))
{
i = 0;
USART_SendData(USART1, 0x2A);
} 
}
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
arlen
Associate II
Posted on August 22, 2016 at 23:42

Hi again clive1

with your suggestion it works fine, but i have some enquiries, when i worked with other ucontroller , when i used its ADC in continuous mode it just overwrite the new data on the old data but it doesn't stop the continuous conversion. The OVERRUN has any porpose in STM uControllers?

I have been testing the part where i receive two conversion and I checked the bit status ADC->SR and at the beginning it has the value 0x10 (STRT: Regular channel  start flag) it is ok , but when the ADC1 stop the conversion , the ADC->SR register has 0x30 (OVR:Over Run) the overun appears, now I could recover the ADC from OVR state and deal with it.

something is not clear to me, the OVERRUN occurs when one or the first EOC is not attended quickly enough or the OVERRUN occurs when a specific numbers of EOC have not been attended?

Is there any function to get the   tick account to estimate the numer of ticks what happend during the execution of a group of instruction, the reasons is to be careful of OVERRUN events.

thanks for your help

Posted on August 23, 2016 at 02:23

I'm not sure of the value of debating what other micro-controllers might tolerate, but here it helps identify failure conditions, or behaviours that are inefficient or broken.

If you have some dependency of processing values in the time-domain, where the placement is critical to the results (ie FFT), then knowing you've got a broken set of numbers helps you understand why you've got a broken set of results.

When would it signal? When it has the next sample, and you haven't read the last one, so in the maximal sense about 2x the sample interval.

How do you count processor cycles? You can use DWT_CYCCNT to read the cycles, and take a beginning and ending values, and delta them.

Use DMA, you can have a volatile variable or array that simply updates continuously and transparently in the background. It will be far more power efficient than banging around in a polling loop doing unproductive work. Ideally have a DMA IRQ trigger processing when data is fully available, and pace the conversion at a desired rate with a TIM.

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