cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 5, 3 & 1 MCU

New Contributor II

Hi all,

I want to make adc read using Interrupt.

But when i debug the code the isr loop call. and did not goes into for(;;) loop.

so the value is not getting.

Here is the code.

CY_ISR(ADC_SAR_2_ISR_LOC)

{

        result = CY_GET_REG16(ADC_SAR_2_SAR_WRK0_PTR);

        dataReady = 1u;

}

int main()

{

    LCD_Start();

    CyGlobalIntEnable; /* Enable all interrupts by the processor. */

    ADC_SAR_2_Start();

    ADC_SAR_2_IRQ_StartEx(ADC_SAR_2_ISR_LOC);

    ADC_SAR_2_StartConvert();

 

  for(;;)

    {

       

        /* Show ADC2 result on LCD*/

        if(dataReady != 0u)

        {

           res1 = ADC_SAR_2_CountsTo_Volts(result);

                   LCD_Position(0u, 0u);

                LCD_PrintString("ADC_Output");

                LCD_ClearDisplay();

                LCD_Position(1u, 2u);

                LCD_PrintNumber(res1);

                LCD_Position(1u, 5u);

                LCD_PrintString("v");

                dataReady = 0u;

        }

               

    }

}

0 Likes
Reply
1 Solution
Esteemed Contributor

Hi,

I think that you need to clear interrupt flag inside the ISR,

otherwise ISR will be called repeatedly.

I modified your code as below and tested with CY8CKIT-059

and at least program flow seems to be working.

Note: As I don't have LCD, I used UART instead.

change USE_LCD to 1 for your system.

=========================

#include "project.h"

#include <stdio.h>

#define USE_LCD 0

#if !USE_LCD

    char str[128] ; /* print buffer */

#endif

volatile int dataReady = 0u ;

uint16_t result = 0 ;

CY_ISR(ADC_SAR_2_ISR_LOC)

{

    ADC_SAR_2_IRQ_ClearPending() ;

    result = CY_GET_REG16(ADC_SAR_2_SAR_WRK0_PTR);

    dataReady = 1u;

}

int main()

{

    float res1 = 0.0 ;

   

#if USE_LCD

    LCD_Start();

#else

    UART_Start() ;

#endif

    CyGlobalIntEnable; /* Enable all interrupts by the processor. */

    ADC_SAR_2_Start();

    ADC_SAR_2_IRQ_StartEx(ADC_SAR_2_ISR_LOC);

    ADC_SAR_2_StartConvert();

  for(;;)

    {

        /* Show ADC2 result on LCD*/

        if(dataReady != 0u)

        {

           res1 = ADC_SAR_2_CountsTo_Volts(result);

#if USE_LCD

                   LCD_Position(0u, 0u);

                LCD_PrintString("ADC_Output");

                LCD_ClearDisplay();

                LCD_Position(1u, 2u);

                LCD_PrintNumber(res1);

                LCD_Position(1u, 5u);

                LCD_PrintString("v");

#else

            sprintf(str, "ADC_Output %d.%02d V\n",

                (int)res1, ((int)(res1 * 100) % 100)) ;

            UART_PutString(str) ;

#endif

            dataReady = 0u;

        }            

    }

}

=========================

moto

View solution in original post

2 Replies
Contributor II

I'm unsure what the problem exactly is.  Are you saying you can't get to your main for(;;) loop because it's not leaving the ISR?  Do you mean you're never getting dataready = 1 or result is not reading the result register properly?

Are result and dataReady declared as volatile?  Any value that you're going to change in an ISR should be declared volatile to ensure the compiler doesn't just assume and optimize incorrectly.  It will basically force the variable to be read before any time it is used rather than assuming it already knows the value.

I'd also recommend not pulling your value from the ADC inside the interrupt.  Set a flag then pull the value into your result variable inside your main for(;;) loop.  That way you can safely use ADC_IsEndConversion() to determine when your conversion has actually finished and ensure you aren't reading until then.  It also minimizes code inside your interrupt.

if (dataReady){

     while (!ADC_IsEndConversion(ADC_RETURN_STATUS){};

     result = ADC_GetResult16();

     dataReady = 0;

}

Esteemed Contributor

Hi,

I think that you need to clear interrupt flag inside the ISR,

otherwise ISR will be called repeatedly.

I modified your code as below and tested with CY8CKIT-059

and at least program flow seems to be working.

Note: As I don't have LCD, I used UART instead.

change USE_LCD to 1 for your system.

=========================

#include "project.h"

#include <stdio.h>

#define USE_LCD 0

#if !USE_LCD

    char str[128] ; /* print buffer */

#endif

volatile int dataReady = 0u ;

uint16_t result = 0 ;

CY_ISR(ADC_SAR_2_ISR_LOC)

{

    ADC_SAR_2_IRQ_ClearPending() ;

    result = CY_GET_REG16(ADC_SAR_2_SAR_WRK0_PTR);

    dataReady = 1u;

}

int main()

{

    float res1 = 0.0 ;

   

#if USE_LCD

    LCD_Start();

#else

    UART_Start() ;

#endif

    CyGlobalIntEnable; /* Enable all interrupts by the processor. */

    ADC_SAR_2_Start();

    ADC_SAR_2_IRQ_StartEx(ADC_SAR_2_ISR_LOC);

    ADC_SAR_2_StartConvert();

  for(;;)

    {

        /* Show ADC2 result on LCD*/

        if(dataReady != 0u)

        {

           res1 = ADC_SAR_2_CountsTo_Volts(result);

#if USE_LCD

                   LCD_Position(0u, 0u);

                LCD_PrintString("ADC_Output");

                LCD_ClearDisplay();

                LCD_Position(1u, 2u);

                LCD_PrintNumber(res1);

                LCD_Position(1u, 5u);

                LCD_PrintString("v");

#else

            sprintf(str, "ADC_Output %d.%02d V\n",

                (int)res1, ((int)(res1 * 100) % 100)) ;

            UART_PutString(str) ;

#endif

            dataReady = 0u;

        }            

    }

}

=========================

moto

View solution in original post