Skip to main content
Visitor II
May 26, 2015
Question

ADC 1 problem with STM8S-Discovery

  • May 26, 2015
  • 4 replies
  • 1887 views
Posted on May 26, 2015 at 13:55

Hi,

I have problem with ADC1 conversions on STM8S-Discovery.

I have configured the analogic inputs following:

PB4 - AN4

PB5 - AN5

PB6 - AN6

unsigned char ADC_Config_INT ( void )

{

    

    GPIO_Init(ADC_PORT,ADC_15V_PIN, GPIO_MODE_IN_FL_NO_IT);

    GPIO_Init(ADC_PORT,ADC_CURR_PIN, GPIO_MODE_IN_FL_NO_IT);

    GPIO_Init(ADC_PORT,ADC_5V_PIN, GPIO_MODE_IN_FL_NO_IT);

 

    /* De-Init ADC1 peripheral */

  ADC1_DeInit();

    

  /* Enable EOC interrupt */

  ADC1_ITConfig(ADC1_IT_EOCIE, ENABLE);

    

  /* Enable conversion data buffering */

  ADC1_DataBufferCmd(ENABLE);

    

  /* Enable scan mode conversion */

  ADC1_ScanModeCmd(ENABLE);

  /* Init ADC1 peripheral */

    /* ADC1 Channel 4 */

  ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_4, ADC1_PRESSEL_FCPU_D8, \

            ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL4,\

            DISABLE);

                        

    /* ADC1 Channel 5 */

  ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_5, ADC1_PRESSEL_FCPU_D8, \

            ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL5,\

            DISABLE);

                        

    /* ADC1 Channel 6 */

  ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_6, ADC1_PRESSEL_FCPU_D8, \

            ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL6,\

            DISABLE);                       

    

  /* Enable ADC1 */

  ADC1_Cmd(ENABLE);

        

    return 0;

}

the interrupt function code is:

#define ADC_SAMPLES 8

extern volatile uint16_t ValueCh4[ADC_SAMPLES];            

extern volatile uint16_t ValueCh5[ADC_SAMPLES];            

extern volatile uint16_t ValueCh6[ADC_SAMPLES];            

volatile uint8_t Index = 0;

extern uint8_t ArrayEmpty;

/**

  * @brief  ADC1 interrupt routine.

  * @param  None

  * @retval None

  */

 INTERRUPT_HANDLER(ADC1_IRQHandler, 22)

{

            if ( ADC1_GetFlagStatus(ADC1_FLAG_EOC) != RESET )

            {

                ValueCh4[Index] = ADC1_GetBufferValue(4);

                ValueCh5[Index] = ADC1_GetBufferValue(5);

                ValueCh6[Index] = ADC1_GetBufferValue(6);

                // Controlla se ho acquisito un numero sufficiente di campioni

                if( Index >= ADC_SAMPLES )

                        {

                            ArrayEmpty = 1;

                            Index = 0;

                        }    

                else{

                            Index++;

                        }

 

                

                ADC1_ClearFlag(ADC1_FLAG_EOC);

            }    

        

    return;

}

The ''ADC1_GetBufferValue'' function return the value correct the first time only.

If I modified the value on pin PB4 for example, continuos at read the previous value.

Any idea?

Thanks
    This topic has been closed for replies.

    4 replies

    u23Author
    Visitor II
    May 28, 2015
    Posted on May 28, 2015 at 14:07

    I attached the project.

    The ADC interrupt is occurs, but the ''ADC1_GetBufferValue(ADC1_CHANNEL_4)'' not

    return the updated value on the channel 4. This function return the read first value.

    A

    ny suggestions?

    Thanks

    ________________

    Attachments :

    Project1.rar : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzNB&d=%2Fa%2F0X0000000bKg%2FfMUpHYx5zpJf69vgPIFnEFm63eHgHQ_e.eRcebHDUa4&asPdf=false
    u23Author
    Visitor II
    June 4, 2015
    Posted on June 04, 2015 at 12:09

    The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6l0&d=%2Fa%2F0X0000000buj%2FjUQeQkRoZH8IXlJ4.jBsmRUt0E9vh9WFtPYC34bTGbo&asPdf=false
    Visitor II
    December 7, 2016
    Posted on December 07, 2016 at 18:05

    I am having a similar issue...  I have to restart the program to refresh this value.

    Visitor II
    January 10, 2017
    Posted on January 10, 2017 at 21:14

    You should read ADC chapter in reference manual again. Your continuous scan mode is always convert N channels (from channel 0) automatically. Multi channel c

    ontinuous scan is not recommend.

    You can combine timer trigger with single mode on each channel, refer post of @LaserElettronicaSRL
    Visitor II
    September 12, 2017
    Posted on September 12, 2017 at 10:10

    Hi

    Problem with conversion in single scan mode is in ADC1->CSR register. After correct conversion it's necessary to reload value of this register by following way:

    ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH);
    ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_5);
    ADC1->CR1 &= (uint8_t)(~ADC1_CR1_CONT);�?�?�?�?�?�?�?

    This 3 lines should be placed in ADC1 INTERRUPT_HANDLER after Interrupt flag clear:

     INTERRUPT_HANDLER(ADC1_IRQHandler, 22)
    {
     /* Clear interrupt flag */
     ADC1_ClearITPendingBit(ADC1_IT_EOC);
     /* Workaround for ADC ScanMode issue (Reconfig ADC) */
     ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH);
     ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_5);
     ADC1->CR1 &= (uint8_t)(~ADC1_CR1_CONT);
     /* User code */
    }�?�?�?�?�?�?�?�?�?�?�?�?�?

    Below I show correct ADC configure for single scan mode with external trigger from TIM1 overflow:

    /* Init timer 1 */
     TIM1_DeInit(); //deinit first configuration
     TIM1_TimeBaseInit(0, TIM1_COUNTERMODE_UP, TIM1_TOP, 0); //set frequency of timer 1
     TIM1_SelectOutputTrigger(TIM1_TRGOSOURCE_UPDATE); //set TRGO active when UPDATE event
     /* Init ADC */
     ADC1_DeInit(); //deinit first configuration of ADC
     ADC1_Init(ADC1_CONVERSIONMODE_SINGLE, //single conversion mode
     ADC1_CHANNEL_5, //in scan mode, this is the last channel to conversion
     ADC1_PRESSEL_FCPU_D4, //set prescaler to 4 (16MHz / 4 = 4MHz [MAX 6MHz])
     ADC1_EXTTRIG_TIM, //select external trigger from timer 1
     ENABLE, //enable external trigger
     ADC1_ALIGN_RIGHT, //align ADC data to right
     ADC1_SCHMITTTRIG_CHANNEL0, //any Schmit trigger
     DISABLE); //because it's disable
     ADC1_ScanModeCmd(ENABLE); //enable scan mode
     ADC1_DataBufferCmd(ENABLE); //enable buffers for ADC
     ADC1_ITConfig(ADC1_IT_EOCIE, ENABLE); //enable End Of Conversion IT
     ADC1_Cmd(ENABLE); //enable ADC�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

    For start conversion we need to start timer and global interrupts:

    /* Enable global interrupt flag */ 
    enableInterrupts();
    /* Enable main measure timer, for ADC triggering */
    TIM1_Cmd(ENABLE);�?�?�?�?�?�?�?�?�?�?

    Now ADC should work correct in single scan mode with external trigger.