Interrupts for multiple ADC configurations

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

cross mob
Anonymous
Not applicable

 Hi,

   

I am running the Delta-Sigma in 3 different configurations (simply to achieve different input ranges), all of which need to have the eoc interrupt running.  The datasheet says that each configuration has a different interrupt routine.  How do I enable the same interrupt each time I switch between configurations?  Also, the datasheet is quite vague about what the ADC_IRQ_Enable() function actually does.  I want to run my own external interrupt hooked up to the eoc pin on the ADC.

   

Thanks.

0 Likes
14 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You have to distinguish between the PSoC-internal interrupt to handle the conversion and the module's output eoc. The latter you will connect to an Isr-module which within your program you'll start preferrably with Isr_StartEx(YourISR). So the internal interrupt (regardless of how many different there are due to the internal configurations) is left untouched.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 As Bob said, Implement the user code in a seperate routine using 

   

CY_ISR_PROTO(MyCustomISR);

   

CY_ISR(MyCustomISR)

   

{     

   

   /* ISR code goes here */    

   

}

   

   

 Call isr_StartEx((MyCustomISR) in main.c to configure and enable the interrupt.

   

 

   

This will result in calling the same routine whenever the ADC conversion is done in ur code and you can check which configuration ADC has completed and update variables accordingly in the isr routine.

   

- srim

0 Likes
Anonymous
Not applicable

Hi kristen,

   

 

   

You can use the internal interrupts available in the ADC_INT.c for individual configurations.

   

CY_ISR(ADC_ISR1), CY_ISR(ADC_ISR2), CY_ADC(ADC_ISR3) and CY_ISR(ADC_ISR4) are the routines which will be executed when EOC occurs when ADC is in Configurations 1,2,3 and 4 respectively.

   

 

   

ADC_IRQ_Start() will enable and start the internal ISR.

   

If you want to use a single ISR for all the configurations, then using a single Interrupt component will do.

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

A sample project is attached along with this comment in which 3 channels are connected to the ADC using AMux. The ADC is operated in 3 configurations.

   

Internal ISRs available in ADC_INT.c is used to set the flag upon conversion (EOC interrupt).

   

The value of the flag determines which configuration the result represents.

   

The flag value of 1 implies result of configuration 1; 2 implies configuration 2; and 3 implies configuration 3.

0 Likes
Anonymous
Not applicable

Thanks for the information.  To explain a bit more, I do want to only use a single ISR for all three configurations.  I have connected a single interrupt component to the eoc pin on the adc as you suggest.  I then use ADC_IRQ_Enable() and isr_StartEx() to enable the interrupt.  This does not seem to work.  Is another step needed after changing configuration each time?

   

Thanks.

0 Likes
Anonymous
Not applicable

The  ADC_IRQ_Start( ) will set the vector address to ADC_ISR1. While implementing user routine, donot use this API

0 Likes
Anonymous
Not applicable

 Can someone please outline the exact steps necessary to do what I am trying to do? (ie. use a single user-defined ISR for three different ADC configurations).  What do I need to do for setup?  What do I need to do each time I change configuration?  

   

Thanks.

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

 Attached the  top design schematic image. See if this works for you.

   

   

#include <device.h>

   

uint16 output;

   

uint16 output1;

   

 

   

CY_ISR(My_Isr_Routine)

   

{

   

ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_WAIT_FOR_RESULT);

   

output = ADC_DelSig_1_GetResult16();

   

output1 = ADC_DelSig_1_GetResult16();

   

}

   

void main()

   

{  

   

        /* Start the components */

   

    CYGlobalIntEnable;

   

    isr_StartEx(My_Isr_Routine);

   

isr_Enable();

   

    LCD_Start();

   

    ADC_DelSig_1_Start();    

   

    /* Start the ADC conversion */

   

    ADC_DelSig_1_StartConvert();    

   

    /* Display the value of ADC output on LCD */

   

    LCD_Position(0, 0);

   

    LCD_PrintString("ADC_Output");   

   

  while(1)

   

    {

   

       ADC_DelSig_1_SelectConfiguration(1,1);

   

               LCD_Position(1, 0);

   

               LCD_PrintInt16(output);

   

               CyDelay(2000);

   

ADC_DelSig_1_Stop();

   

       ADC_DelSig_1_StopConvert();

   

//ADC_DelSig_1_SelectConfiguration(1,0);

   

            LCD_ClearDisplay();        

   

       ADC_DelSig_1_SelectConfiguration(2,1);        

   

ADC_DelSig_1_Start();       

   

            ADC_DelSig_1_StartConvert();

   

            LCD_Position(1, 10);

   

            LCD_PrintInt16(output1);

   

CyDelay(2000);

   

LCD_ClearDisplay();

   

}

   

}

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

kristen,

   

 

   

What I understand from your statement is thet you are using ADC with 3 different configurations and want to use EOC signal to detect the end of conversion.However, you want to have a single location from where you can execute the code when you get EOC for all the three configurations together.

   

 

   

A simple solution is to use an Interrupt component, and connect it to EOC of ADC.

   

1) Start the Interrupt Component.

   

2) Remember that when you are using Interrupt, you need not poll for the conversion to complete. Hence using the API ADC_IsEndConversion( ) is redundant.

   

3) Since you are using multi-channel ADC, it is important for you to know which channel result you received upon EOC interrupt. Hence, keeping track of the channel number is necessary in the firmware.

   

4) Before starting any conversion, make sure that the StopConvert( ) is executed. This will prevent cross-talk between two channels.

   

These have been incorporated in the project attached.

0 Likes
Anonymous
Not applicable

 Hi,

   

Ok, so from what I understand of what everyone is saying, my current setup is correct.  Please correct me if I'm wrong.  I have an isr (adc_isr) component connected to the eoc pin on the ADC in the GUI.  I have written my own isr function (a single one for use across all configurations).  In main(), I have written the following intialisation code.  I have not used ADC_IRQ_Start() or ...Enable().    

   

        ADC_Start();

   

//set ADC to config 2

   

ADC_SelectConfiguration(2, 0);

   

ADC_Start();

   

//initialise interrupts

   

    CYGlobalIntEnable;

   

adc_isr_StartEx(ADCInterrupt);

   

In my .cydwr file, I can see though that the ADC_IRQ is nonetheless enabled.  I am assuming that this is to enable the eoc pin on the ADC in the GUI to trigger an interrupt.  I don't understand though why there need to be two different interrupts enabled (ADC_IRQ and adc_isr) at the same time.  

   

I am currently encountered a very strange bug, where the ADC_IRQ appears to be writing to one of my global variables illegally.  I want to disable this interrupt if possible, but I don't entirely understand the dual presence of the two ADC eoc interrupts.  Can someone please enlighten me?  Thanks.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

The interrupt you have seen is for the INTERNAL use of the ADC. As you know, the samples run into an internal filter and there are some stage-dependent-calculations to perform. At the very end of the internal interrupt (at the last stage) the eoc-line is pulled up, so that you get informed or receive control.

   

To avoid strange side-effects

   

In your ISR only(!!!)  set a flag, in your main-loop check for the flag, act on it (get ADC-value) and reset the flag.

   

when this runs, change your ISR to do (a bit) more. Watch out for warnings of procedures called from different locations (I've forgotten the exact errormessage)

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 Thanks Bob.  Is it possible though to disable the ADC_IRQ?  What is its connection to the external isr component?  I want my isr to run on end of conversion, but I would like to be able to ensure that no other interrupts that I don't have control over are also running.  As I mentioned, I believe that the internal interrupt being enabled is causing a bug in my software.  I would like to at least be able to test it with it disabled if that is possible.  If I disable global interrupts, I don't see the bug, but disabling each interrupt individually (including ADC_IRQ) does not have the same effect for some reason.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

The ADC won't run with interrupst disabled. The internal ADC-interrupt is not interfering by spoiling a value, the error will be in a different area. Do as I suggested, just set a flag in the ISR and poll for it in the main-loop. You may post your project here. To do so:

   

Build->Clean Project

   

File->Create Workspace Bundle(minimal)

   

and attach the zip-file. I'll have a look at it.

   

Bob

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

There are reasons for vars get spoiled, but that are few:

   

1st and common is a stack overflow (usually caused by interrupts) A common mistake can be not to clear the source of the interrupt (reading the Status_Register if there is one).

   

2nd there can be a pointer pointing into electronic nirwana. I recently found out, that in PSoC3 under some special circumstances a NULL pointer isn't NULL, but that cases are rare.

   

I would try to eleminate case #1 and I would check for ANY design- or compiler warnings and use a zero-warning-program.

   

 

   

Bob

0 Likes