EmbeddedRelated.com
Forums

stuck in ADC interrupt

Started by "yass.engineer" September 4, 2010
Hello Guys,

I am using Crossworks and I realized that whenever I have AD0_INTEN initialised to: AD0_INTEN = 0xFF; Then I will be stuck in my ADC ISR routine.

If I leave AD0_INTEN to its default value where only ADGINTEN is set then my firmware works correctly.

This is my ISR:

static void AD0ISR(void)
{
unsigned int chan, val;
val = AD0_GDR;
val = ((val >> 6) & 0x03FF);
chan = ((AD0_GDR >> 0x18) & 0x07;
if(chan==7)
AD0_CR &= ~AD_CR_BURST; // stop repeated conversion

VIC_VectAddr = 0;
}

Any help please.

Thanks

An Engineer's Guide to the LPC2100 Series

On 09/04/2010 05:07 PM, yass.engineer wrote:
> I am using Crossworks and I realized that whenever I have AD0_INTEN
> initialised to: AD0_INTEN = 0xFF; Then I will be stuck in my ADC ISR
> routine.

There is DONE bit for each channel which is the one generating the
interrupt if you have enabled it in the INTEN register (at least in 2648
- you didn't specify which controller). You must clear it by reading the
corresponding DR before leaving the ISR. Otherwise, it will trigger a
new interrupt every time you try to leave the ISR.

> If I leave AD0_INTEN to its default value where only ADGINTEN is set
> then my firmware works correctly.

You happen to clear the global DONE bit by reading the GDR.

> This is my ISR:
>
> static void AD0ISR(void)
> {
> unsigned int chan, val;
> val = AD0_GDR;
> val = ((val >> 6) & 0x03FF);

This doesn't have anything to do with your problem at hand but,
nevertheless, I realized that you are reading the GDR twice. That's bad.
It is performance hit and think about what happens, if the last
conversion becomes ready exactly at this point. Do it...

> chan = ((AD0_GDR >> 0x18) & 0x07;
> if(chan==7)
> AD0_CR &= ~AD_CR_BURST; // stop repeated conversion
>
> VIC_VectAddr = 0;
> }

...like this:

val = AD0_GDR;
chan = val >> 0x18 & 0x07;
val = val >> 6 & 0x03FF;

--

Timo
Hi Timo,

Thnaks for your help .You are always there.

Sorry for my last message. It was sent by mistake.

I am using LPC2148.Can you please let me know where is the risk in reading the register two times?

Regards

--- In l..., Timo wrote:
>
> On 09/04/2010 05:07 PM, yass.engineer wrote:
> > I am using Crossworks and I realized that whenever I have AD0_INTEN
> > initialised to: AD0_INTEN = 0xFF; Then I will be stuck in my ADC ISR
> > routine.
>
> There is DONE bit for each channel which is the one generating the
> interrupt if you have enabled it in the INTEN register (at least in 2648
> - you didn't specify which controller). You must clear it by reading the
> corresponding DR before leaving the ISR. Otherwise, it will trigger a
> new interrupt every time you try to leave the ISR.
>
> > If I leave AD0_INTEN to its default value where only ADGINTEN is set
> > then my firmware works correctly.
>
> You happen to clear the global DONE bit by reading the GDR.
>
> > This is my ISR:
> >
> > static void AD0ISR(void)
> > {
> > unsigned int chan, val;
> > val = AD0_GDR;
> > val = ((val >> 6) & 0x03FF);
>
> This doesn't have anything to do with your problem at hand but,
> nevertheless, I realized that you are reading the GDR twice. That's bad.
> It is performance hit and think about what happens, if the last
> conversion becomes ready exactly at this point. Do it...
>
> > chan = ((AD0_GDR >> 0x18) & 0x07;
> > if(chan==7)
> > AD0_CR &= ~AD_CR_BURST; // stop repeated conversion
> >
> > VIC_VectAddr = 0;
> > }
>
> ...like this:
>
> val = AD0_GDR;
> chan = val >> 0x18 & 0x07;
> val = val >> 6 & 0x03FF;
>
> --
>
> Timo
>

On 09/05/2010 04:36 PM, yass.engineer wrote:
> Thnaks for your help .You are always there.

Thanks for hearty thought.

> I am using LPC2148.Can you please let me know where is the risk in
> reading the register two times?

If one of the conversions completes right in between the two register
reads, you lose one conversion result. Think about it:
Conversion completes, DONE bit is set

Interrupt is triggered

You read the GDR, DONE bit is cleared

Another conversion completes, DONE bit is set

You read the GDR again, DONE bit is cleared
So in one interrupt you cleared two conversions but got only one value.
Next interrupt is not triggered until the third conversion completes. If
you read the register only once, DONE-bit remains set and you get second
interrupt.

--

Timo
Hi,
Can you please tell me how I could know the time needed to execute my adc ISR. I am using crossworks.

Regards

--- In l..., Timo wrote:
>
> On 09/05/2010 04:36 PM, yass.engineer wrote:
> > Thnaks for your help .You are always there.
>
> Thanks for hearty thought.
>
> > I am using LPC2148.Can you please let me know where is the risk in
> > reading the register two times?
>
> If one of the conversions completes right in between the two register
> reads, you lose one conversion result. Think about it:
> Conversion completes, DONE bit is set
>
> Interrupt is triggered
>
> You read the GDR, DONE bit is cleared
>
> Another conversion completes, DONE bit is set
>
> You read the GDR again, DONE bit is cleared
> So in one interrupt you cleared two conversions but got only one value.
> Next interrupt is not triggered until the third conversion completes. If
> you read the register only once, DONE-bit remains set and you get second
> interrupt.
>
> --
>
> Timo
>

yass.engineer wrote:
> Can you please tell me how I could know the time needed to execute my
> adc ISR. I am using crossworks.

Set an I/O-pin at the start of the ISR and clear it at the end and then take a
look with a scope. That's how I would do it but of course only one option of many.

--

Timo