cancel
Showing results for 
Search instead for 
Did you mean: 

[SOLVED] STM32l152c Discovery board, Cant see my problem getting ADC working

julian2399
Associate II
Posted on September 22, 2015 at 13:29

Initialisation call from main
adc_setup_data.adc_block = ADC1;
adc_setup_data.adc_channel = 1;
adc_setup_data.adc_number_of_bits = ADC_Resolution_12b;
adc_setup_data.adc_sample_time = ADC_SampleTime_16Cycles;
adc_setup_data.adc_GPIOx = GPIOA;
adc_setup_data.adc_gpio_pin = GPIO_Pin_1;
adc_init( adc_poll_callback, &adc_setup_data);
The routine itself
int adc_init( adc_poll_data poll_cb, void *user_data)
{
ADC_CommonInitTypeDef prescale;
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
adc_setup *setup = user_data;
if( !IS_ADC_ALL_PERIPH(setup->adc_block)) {
return -1;
}
if( !IS_ADC_CHANNEL(setup->adc_channel)) {
return -1;
}
if( !IS_ADC_RESOLUTION(setup->adc_number_of_bits)) {
return -1;
}
if( !IS_ADC_SAMPLE_TIME( setup->adc_sample_time)) {
}
/* Common Prescaler for ADC */
prescale.ADC_Prescaler = ADC_Prescaler_Div4; /* ADC_Prescaler_Div1, ADC_Prescaler_Div2 or ADC_Prescaler_Div4 */
ADC_CommonInit(&prescale);
if( setup->adc_block == ADC1) {
RCC_PCLK2Config(RCC_HCLK_Div16);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
}
else {
return -1;
}
adc_data.adc.ADCx = setup->adc_block;
adc_data.adc.adc_channel = setup->adc_channel;
adc_data.adc.adc_last_value = (1<<
12
) + 1;
adc_data.adc.adc_differential
= 
8
;
adc_data.queue
= 
queue_create
(5);
adc_data.running
= 
FALSE
;
adc_data.poll_callback
= 
poll_cb
;
adc_data.poll_user_data
= user_data;
// Init the GPIO with the structure
GPIO_InitStructure.GPIO_Pin
= 
setup
->adc_gpio_pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(setup->adc_GPIOx, &GPIO_InitStructure);
ADC_DeInit(setup->adc_block);
/* Configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Resolution = setup->adc_number_of_bits;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(setup->adc_block, &ADC_InitStructure);
//configure channel
ADC_RegularChannelConfig(setup->adc_block, setup->adc_channel, 1, setup->adc_sample_time);
//Enable channel
ADC_Cmd(setup->adc_block, ENABLE);
return 1;
}
 Ive walked this code and cannot see what im doing wrong, but every read from the ADC os 0x000
 Any help
 joolz

11 REPLIES 11
Posted on September 22, 2015 at 14:12

You enable the HSI clock somewhere?

/* Enable The HSI (16Mhz) */
RCC_HSICmd(ENABLE);
/* Check that HSI oscillator is ready */
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
julian2399
Associate II
Posted on September 22, 2015 at 14:46

Thanks for the reply but I added your code as a just in case as this is someone elses project and still get back 0x000

I also added a DAC output on DAC2 and wired this to the ADC input and put a fixed value of 2048, but ADC reads 0x000. Is is possible with a direct connection!

joolz

AvaTar
Lead
Posted on September 22, 2015 at 15:05

> I also added a DAC output on DAC2 and wired this to the ADC input and put a fixed value of 2048, but ADC reads 0x000. Is is possible with a direct connection!

 

No.

ST's DAC periphery is low-current/high impedance. Even with enabled output buffer, the DAC is usually not capable of driving the ADC properly. Presenting the DAC initialization code here might be helpful.

Better use a potentiometer with 5 .. 10k, that should work for all sample times, is easy to check with a voltmeter, and eliminates additional code in the loop (== additional sources of trouble).

How do you trigger a conversion ?

How do you get the result back ? I have seen neither a interrupt nor a DMA initialization.

AvaTar
Lead
Posted on September 22, 2015 at 15:07

Crappy forum !!!

 

 

julian2399
Associate II
Posted on September 22, 2015 at 15:08

The code is based on a JOB system and this is called on a 100ms bases

      ADC_SoftwareStartConv(adc_data.adc.ADCx);

      while( ADC_GetSoftwareStartConvStatus(adc_data.adc.ADCx) == RESET) {

      }

      adc_data.adc.adc_value = ADC_GetConversionValue(adc_data.adc.ADCx);

joolz

julian2399
Associate II
Posted on September 22, 2015 at 15:14

#if DEBUG_DAC

    // DAC  PA5 DAC_OUT2

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

    // initialize DAC

    DAC_InitTypeDef dacInitStruct;

    dacInitStruct.DAC_Trigger = DAC_Trigger_None;

    dacInitStruct.DAC_OutputBuffer = DAC_OutputBuffer_Enable;

    dacInitStruct.DAC_WaveGeneration = DAC_WaveGeneration_None;

    // initialize both DAC channels with structure settings above

    DAC_Init(DAC_Channel_2, &dacInitStruct);

    // enable both DAC channels

    DAC_Cmd(DAC_Channel_2, ENABLE);

    dac_value = 0;

    dac_increase = 128;

    DAC_SetChannel2Data(DAC_Align_12b_R, dac_value);

#endif

and in my main loop every second i do the following

#if DEBUG_DAC

      dac_value += dac_increase;

      DAC_SetChannel2Data(DAC_Align_12b_R, dac_value);

      if( !dac_value || dac_value==2048) {

          dac_increase =-dac_increase;

      }

#endif

From: gardner.julian

Posted: Tuesday, September 22, 2015 3:08 PM

Subject: STM32l152c Discovery board, Cant see my problem getting ADC working

The code is based on a JOB system and this is called on a 100ms bases

      ADC_SoftwareStartConv(adc_data.adc.ADCx);

      while( ADC_GetSoftwareStartConvStatus(adc_data.adc.ADCx) == RESET) {

      }

      adc_data.adc.adc_value = ADC_GetConversionValue(adc_data.adc.ADCx);

joolz

AvaTar
Lead
Posted on September 22, 2015 at 15:19

while( ADC_GetSoftwareStartConvStatus(adc_data.adc.ADCx) == RESET)

I think this line does not do what you think it does:

/**
* @brief Gets the selected ADC Software start regular conversion Status.
* @param ADCx: where x can be 1 to select the ADC1 peripheral.
* @retval The new state of ADC software start conversion (SET or RESET).
*/
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx)

This is what the StdPeripheralLib says about it (STM32L1xx, V1.3.1). You rather want to know when the conversion is finished. But why not taking the simple approach of ST's (old) peripheral examples, and configure continuous mode ? That would suffice if you don't need synchronized readout i.e. don't have sampling frequency constraints.
AvaTar
Lead
Posted on September 22, 2015 at 16:06

Some additional comments:

>   dacInitStruct.DAC_OutputBuffer = DAC_OutputBuffer_Enable;

 

 

This suggests your DAC is set to 15k output impedance (never used the L1xx ADC/DAC peripherals, so better check the datasheet). This might be enough to drive the ADC for low sampling times.

But I still prefer the potentiometer method - testing code with other untested code is not the best idea.

>      ADC_SoftwareStartConv(adc_data.adc.ADCx);

 

>      while( ADC_GetSoftwareStartConvStatus(adc_data.adc.ADCx) == RESET) {

 

>      }

 

>      adc_data.adc.adc_value = ADC_GetConversionValue(adc_data.adc.ADCx);

 

Besides of my comment about the ADC_GetSoftwareStartConvStatus() function, polling seems the least appropriate method. You just waste hundreds of CPU cycles.

Either use the continuous mode, and simply fetch the results regularly, or configure a timer as trigger (set up for 100ms), and fetch the results in the ADC interrupt routine.

Using DMA for a single channel with that low sample rate seem an overkill to me.

Seems you are using a RTOS, don't know if that gets in your way. I only used bare-metal up to now.

julian2399
Associate II
Posted on September 23, 2015 at 12:28

Ok added 2 resistors 10K from gnd and vdd, connected to the ADC input.

Added in code to read the ADC input via a TIM3 interrupt, still getting 0x0000.

Completely confused as I have look at numerous examples and cant see what im doing wrong.

void TIM3_IRQHandler(void)

{

  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

  adc1_read_value = adc_data.adc.ADCx->DR;

  ADC_SoftwareStartConv(adc_data.adc.ADCx);

}

Disabled the DAC as its not needed.

Interrupt gets fired off at the desired rate 10 per second.

And nothing from ADC, i know im missing a real simple step but i cant find it.

joolz