ADC SAR which channel produce interrupt

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
bridzysta
Level 1
Level 1
5 sign-ins First question asked Welcome!

Hello all,

I got a problem with ADC. Here is what I want to do. I want to measure voltage on 4 channels (use differential mode, not single-ended). I want to measure an average value from ADC input based on 10000 samples. I also want to do this inside interrupt - but when I try it all cruches..

Inside ADC_SAR_Seq_1_INT.c I got something like this:

 

/*******************************************************************************
* File Name: ADC_SAR_Seq_1_INT.c
* Version 2.40
*
*  Description:
*    This file contains the code that operates during the ADC_SAR interrupt
*    service routine.
*
*   Note:
*
********************************************************************************
* Copyright 2008-2015, Cypress Semiconductor Corporation.  All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/

#include "ADC_SAR_Seq_1.h"
#include "cyapicallbacks.h"


/******************************************************************************
* Custom Declarations and Variables
* - add user inlcude files, prototypes and variables between the following
*   #START and #END tags
******************************************************************************/
/* `#START ADC_SYS_VAR`  */

#define "adc.h"

extern int16 dataReady;

extern int16 result_0;
extern int16 result_1;
extern int16 result_2;
extern int16 result_3;

/* `#END`  */

#if(ADC_SAR_Seq_1_IRQ_REMOVE == 0u)


    /******************************************************************************
    * Function Name: ADC_SAR_Seq_1_ISR
    *******************************************************************************
    *
    * Summary:
    *  Handle Interrupt Service Routine.
    *
    * Parameters:
    *  None.
    *
    * Return:
    *  None.
    *
    * Reentrant:
    *  No.
    *
    ******************************************************************************/
    CY_ISR( ADC_SAR_Seq_1_ISR )
    {
        uint32 intr_status;

        /* Read interrupt status register */
        intr_status = ADC_SAR_Seq_1_SAR_INTR_REG;

        #ifdef ADC_SAR_Seq_1_ISR_INTERRUPT_CALLBACK
            ADC_SAR_Seq_1_ISR_InterruptCallback();
        #endif /* ADC_SAR_Seq_1_ISR_INTERRUPT_CALLBACK */


        /************************************************************************
        *  Custom Code
        *  - add user ISR code between the following #START and #END tags
        *************************************************************************/
        /* `#START MAIN_ADC_ISR`  */
        
        result_0 = GetADCValue(0);
        result_1 = GetADCValue(1);
        result_2 = GetADCValue(2);
        result_3 = GetADCValue(3);
        //This works!
        //result_0 = ADC_SAR_Seq_1_GetResult16(0);
        //result_1 = ADC_SAR_Seq_1_GetResult16(1);
        //result_2 = ADC_SAR_Seq_1_GetResult16(2);
        //result_3 = ADC_SAR_Seq_1_GetResult16(3);

        dataReady = 1;
        
        /* `#END`  */
        
        /* Clear handled interrupt */
        ADC_SAR_Seq_1_SAR_INTR_REG = intr_status;
    }

#endif   /* End ADC_SAR_Seq_1_IRQ_REMOVE */


/* [] END OF FILE */

 

 

My function GetADCValue looks like this:

 

#define SAMPLES 10000

int GetADCValue(int ChanelNumber)
{
    int loopCtr = 0;
    int sum;
    float adc_0;
    float sum_0 = 0;

    for(loopCtr = 0; loopCtr < SAMPLES; ++loopCtr)
    {
        adc_0 = ADC_SAR_Seq_1_GetResult16(ChanelNumber);
        if (adc_0 > 0)
        {   
            sum_0 = sum_0 + adc_0;
        }
        else
        {
            sum_0 = sum_0 - adc_0;
        }
    }
    sum_0 = sum_0/SAMPLES;
    sum = (int)sum_0;

    return sum;
}

 

 

I think that my calculation takes too much time of processor.. I have idea to maybe read one time in interrupt value from ADC - but from which channel should I read? How can I know which channel (0, 1, 2 or 3) causes interrupt?

Here you got my setting of ADC.

ADC_SARADC_SAR

adc_2.PNG

 

adc_3.PNG

adc_4.PNG

In the main.c I also call my function ADCInit which looks like this:

 

void ADCInit(void)
{
    ADC_SAR_Seq_1_Start();
    ADC_SAR_Seq_1_IRQ_Enable();
    ADC_SAR_Seq_1_StartConvert();
}

 

 

Thank guys for help and anny suggestions! Wish all of You a Happy New Year :)!

0 Likes
3 Replies
Raj_C
Moderator
Moderator
Moderator
250 solutions authored 500 replies posted 50 likes received

Hi @bridzysta,

Can you please share your project file if possible? So, I can understand and help with your implementation.

Thank you

Best Regards

Raj Chaudhari

0 Likes
RodolfoGL
Employee
Employee
250 solutions authored 250 sign-ins 5 comments on KBA

An ADC interrupt occurs every time the ADC scans all the configured channels, in your case 4 channels. So you are supposed to read only 4 samples (one for each channel) per interrupt.

Your GetADCValue() reads 1000 samples. It should only read one sample. 

It seems you want to implement an average filter in your ISR. Note that the ADC block has a feature to do that in hardware. It is called "Samples Averaged". 

0 Likes
Raj_C
Moderator
Moderator
Moderator
250 solutions authored 500 replies posted 50 likes received

Hi @bridzysta,

The thread was locked due to inactivity for a long time, you can continue the discussion on the topic by opening a new thread with reference to the locked one. The continuous discussion in an inactive thread may mostly be unattended by community users.

Thanks and Regards,
Raj Chaudhari
Cypress Semiconductor Corporation
An Infineon Technologies Company

0 Likes