ADC Burst Mode

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

ADC Burst Mode

5,510 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by avass on Tue Jan 22 02:06:58 MST 2013
Is there a way to just have one hardware scan done on a selected ADs in order to avoid OVERRUN?

I'm starting a BURST reading from a timer interrupt and generate interrupt on when a given channel is done being read. When I process this interrupt, half-the time the OVERRUN flag is set...

Any ideas?

Thx,
0 Kudos
11 Replies

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by avass on Sat Jan 26 02:33:52 MST 2013

Quote: Rob65
Embedded Artists shows a video on the webpage with the LPCXpresso Experiment Kit and there Anders Rosvall explains (at 1:50) that embedded programming is "multi-disciplinary". Reading (and understanding) datasheets and user manuals is one of those things.
Most user manuals read like a book of laws, you need to combine text from multiple sections and sometimes even read in between the lines to understand what is truly meant.



Agreed. Although it applies to all other fields as well ( not only embedded programming, but cooking too ) if we want to cover the philosophical aspects... :D


Quote: Rob65
To start with, I downloaded the lpc111x user manual (I read in another topic you are using the lpc1115).

It does ...
The description of the A/D Global Data Register (25.5.2) and the other A/D Data Registers (25.5.4) tell the following:

[LIST=1]
[*]1. V_VREF: When DONE = 1, this bit contains a binary fraction representing the voltage on the ADn pin, ...
[*]2. DONE is set to one when an A/D conversion completes, it is cleared by reading the register
[*]3. OVERRUN if the result in V_VREF was lost and overwritten before read
[/LIST]
Combine 1 and 2 and you'll see that V_VREF is only written with the value of a full conversion. Combine this with 3 and it's clear that this means that a previous conversion value is overwritten with a new one.



Yes and No. I've read way too many errata documents to assume what you have just assumed. And we all know, assumptions lead to mistakes. My favorite one regarding Cortex is the "fact" that HYS and MODE values have no effect when configuring pins for ADC. Yet, if you set [I]pull-up resistor enabled[/I] in mode for the M0's ADC, you end up with skewed values... So, I learnt to be humble... :(


Quote: Rob65
So even without bothering about the OVERRUN bit, when using the converter in BURST mode you can always just read the data register with any form of (software) timing. The only thing is that having your ADC in continuous burst mode takes some extra power which is not that nice when using battery powered applications.



Agreed, that is exactly why I am triggering the bursts from a timer and stop them from the ADC interrupt handler.


Quote: Rob65
The conversion stops when it's done and, when stopped, the data is written into the A/D Data Register and the DONE bit is set.

You could just read the status register and check the DONE bits but it is nicer to use interrupts, as you wrote in one of your previous posts.



Indeed.


Quote: Rob65
The A/D interrupt enable register contains 9 bits (8 for each channel and one for the global data register). You will not use the ADGINTEN (Global DONE) since this interrupts on every conversion.
Instead, enable the ADINTEN bit for the highest channel used. When this interrupt triggers you can read the A/D Data Registers of all enabled channels.

So with A/D channels 0, 3, 4 and 6 enabled (bits set in the SEL field in the A/D Control Register), set the ADINTEN bit for channel 6.
After the conversion of channels 0, 3, 4 and 6 completes the last one will generate the interrupt.

Please note: I am kind of assuming that the conversion takes place in a logical order; so first channel 0, then 3, then 4 and then 6. I might have read this somewhere but cannot find this in the user manual. So this is one of those times where you have to read in between the lines and just assume the order will be logical. I think there is a separate application note on the A/D converter telling this or maybe I used some old information from previous chips that use the same - or a similar - A/D converter.



It is clearly spelled out in the manual indeed and I am using it ( 25.5.1 ADCR's BURST bit description for Hardware scan mode )

I'm also stopping the conversion on one channel ahead as while the interrupt arrives the now-last conversion is already under way and while the interrupt handler actually gets to the code which reads the Data Registers, the conversion is done...


Quote: Rob65
So knowing all this you should be able to write your software:
Use the match output of a timer (there is no need to place the match signal on a pin, there is an internal connection between the match output of the timers and the A/D converter) to start the conversion. And use the A/D interrupt to read your signals.

What I did not check is if the timer keeps running so you have a fixed timing or if you need to reset the timer from an interrupt function each time.
Something to figure out yourself I guess.
And ... report it back to this thread I want to use this mechanism in my own application also :D



Thanks Rob, as my original posting shows, I've been doing this from the beginning; the timer match resets the timer value while generating the interrupt from which the burst is triggered. That part was very simple. [U]By comparing counters in the timer and the AD interrupt handler I even know if the timer is too fast, which is still OK at 1000 samples/sec...[/U]

What I really wanted to know in this post if there is any way to instruct the hardware scan mode to do only one sweep instead of continuous one, as I did not find it in the manual... And if not, maybe we can influence ARM to include it in future HW if there is a need... I could certainly use it to conserve energy...

Thanks for your help.
0 Kudos

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Sat Jan 26 01:18:40 MST 2013

Quote: avass
Thanks Rob, I've read the manual. If it was THAT clear, I would've not asked the question


Embedded Artists shows a video on the webpage with the LPCXpresso Experiment Kit and there Anders Rosvall explains (at 1:50) that embedded programming is "multi-disciplinary". Reading (and understanding) datasheets and user manuals is one of those things.
Most user manuals read like a book of laws, you need to combine text from multiple sections and sometimes even read in between the lines to understand what is truly meant.


Quote:

... :confused:  What the manual does not clearly state is that WITH WHAT was the previous conversion overwritten with.

To start with, I downloaded the lpc111x user manual (I read in another topic you are using the lpc1115).

It does ...
The description of the A/D Global Data Register (25.5.2) and the other A/D Data Registers (25.5.4) tell the following:

[LIST=1]
[*]1. V_VREF: When DONE = 1, this bit contains a binary fraction representing the valtage on the ADn pin, ...
[*]2. DONE is set to one when an A/D conversion completes, it is cleared by reading the register
[*]3. OVERRUN if the result in V_VREF was lost and overwritten before read
[/LIST]
Combine 1 and 2 and you'll see that V_VREF is only written with the value of a full conversion. Combine this with 3 and it's clear that this means that a previous conversion value is overwritten with a new one.


So even without bothering about the OVERRUN bit, when using the converter in BURST mode you can always just read the data register with any form of (software) timing. The only thing is that having your ADC in continuous burst mode takes some extra power which is not that nice when using battery powered applications.



Quote:

About the [B]Scan Once Then Stop[/B], the manual says [I]"If the BURST bit in the ADCR0 is 0 and the START field contains 010-111, the A/D converter will start a conversion when a transition occurs on a selected pin or timer match signal."[/I]. May I ask how is this applicable to [B]stopping[/B] the conversion on a given channel?

The conversion stops when it's done and, when stopped, the data is written into the A/D Data Register and the DONE bit is set.

You could just read the status register and check the DONE bits but it is nicer to use interrupts, as you wrote in one of your previous posts.

The A/D interrupt enable register contains 9 bits (8 for each channel and one for the global data register). You will not use the ADGINTEN (Global DONE) since this interrupts on every conversion.
Instead, enable the ADINTEN bit for the highest channel used. When this interrupt triggers you can read the A/D Data Registers of all enabled channels.

So with A/D channels 0, 3, 4 and 6 enabled (bits set in the SEL field in the A/D Control Register), set the ADINTEN bit for channel 6.
After the conversion of channels 0, 3, 4 and 6 completes the last one will generate the interrupt.

Please note: I am kind of assuming that the conversion takes place in a logical order; so first channel 0, then 3, then 4 and then 6. I might have read this somewhere but cannot find this in the user manual. So this is one of those times where you have to read in between the lines and just assume the order will be logical. I think there is a separate application note on the A/D converter telling this or maybe I used some old information from previous chips that use the same - or a similar - A/D converter.

So knowing all this you should be able to write your software:
Use the match output of a timer (there is no need to place the match signal on a pin, there is an internal connection between the match output of the timers and the A/D converter) to start the conversion. And use the A/D interrupt to read your signals.

What I did not check is if the timer keeps running so you have a fixed timing or if you need to reset the timer from an interrupt function each time.
Something to figure out yourself I guess.
And ... report it back to this thread I want to use this mechanism in my own application also :D

Regards,

Rob
0 Kudos

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by avass on Fri Jan 25 21:52:33 MST 2013

Quote: Rob65
Wow wow wow ...
Normally I'm not this harsh but please take care of what you write. If you can't find what you are looking for then don't just blame the writer...
Especially on this issue (overrun) the manual is very clear:
This bit is 1 in burst mode if the results of one or more conversions was (were) lost 0 and overwritten before the conversion that produced the result in the RESULT bits.


So it indeed just tells you that one or more results have not been read before a new value was available.

With regard to the scan once Then stop mode that avass is looking for, this is possible when using hardware triggered mode using e.g. A timer match output. Set the bits of the channels you want to scan in the SEL bits, set BURST to 0 and any of the modes 010 to 111 in the ADCR register as described in the section "hardware triggered conversion".

Rob



Thanks Rob, I've read the manual. If it was THAT clear, I would've not asked the question... :confused:  What the manual does not clearly state is that WITH WHAT was the previous conversion overwritten with. Was it the latest measured value ( which would be expected ) or is it BEING overwritten or invalidated, thus the value is invalid. Based on the manual, I do not know if I can trust the data value for the channel on which the OVERRUN flag is set. Do you? Your insight / hardware knowledge is appreciated.

About the [B]Scan Once Then Stop[/B], the manual says [I]"If the BURST bit in the ADCR0 is 0 and the START field contains 010-111, the A/D converter will start a conversion when a transition occurs on a selected pin or timer match signal."[/I]. May I ask how is this applicable to [B]stopping[/B] the conversion on a given channel?

Thanks.
0 Kudos

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by karanmehta93 on Wed Jan 23 14:21:55 MST 2013
Check this out for your requirements.
#include<LPC17xx.h> //Always Put this header file on the top of the code else u will get errors
#include"LPC17xx_1.h"
#include"PLL.h"
#include"NVIC.h"
#include"ADC.h"

/* To Start ADC first Enable ADC interrupts in NVIC using
Enable(ADC);
Then config the pins we want to use as ADC channels by the function ConfigADC()
and channel as argument. This uses PINSEL reigsters to select the ADC function on the given pin.
ConfigADC(Adc1);
When we want to start receiving values of ADC conversion we wil have to enable the individual ADC channel interrupts
For this, use the EnableADC() function as 
EnableADC(Adc1);
This line will start the interrupt on desired channel. Whenever the conversion is complete an interrupt is called which
transfers the value into ADCval[n] variable.
To stop the ADC channel, simply call the DisableADC() function as follows
DisableADC(Adc1);
To get the final value for ADC channel no. nrefer to the variable ADCval[n].
*/
void ConfigADC(int channel)
{ 
PCONP |= 0x00001000;
  int adc_clkdiv;
AD0INTEN &= 0xFF;
switch (channel){

case Adc0:
PINSEL1 &= ~0x0000C000;
PINSEL1 |=  0x00004000;
break;
case Adc1:
PINSEL1 &= ~0x00030000;
PINSEL1 |=  0x00010000;
break;
case Adc2:
      PINSEL1 &= ~0x000C0000;
PINSEL1 |=  0x00040000; 
     break;
case Adc3:
    PINSEL1 &= ~0x00300000;
PINSEL1 |=  0x00100000;
     break;
case Adc4:
PINSEL3 &= ~0x30000000;
PINSEL3 |=  0x30000000;
break;
case Adc5:
PINSEL3 &= ~0xC0000000;
PINSEL3 |=  0xC0000000;
break;
case Adc6:
PINSEL0 &= ~0x00000030;
PINSEL0 |=  0x00000080;
break;
case Adc7:
PINSEL0 &= ~0x000000C0;
PINSEL0 |=  0x00000020; 
break;
}
adc_clkdiv = 4;
AD0CR |= 1<<channel;
AD0CR |= adc_clkdiv<<8 | 1<<16 | 1<<21;
}
void EnableADC(int channel)
  {
AD0INTEN |= 1<<channel;
}
void DisableADC(int channel)
  {
switch(channel)
  {
case Adc0:
  AD0INTEN &= 0xFE;
break;
case Adc1:
  AD0INTEN &= 0xFD;
break;
case Adc2:
  AD0INTEN &= 0xFB;
break;
case Adc3:
  AD0INTEN &= 0xF7;
break;
case Adc4:
  AD0INTEN &= 0xEF;
break;
case Adc5:
  AD0INTEN &= 0xDF;
break;
case Adc6:
  AD0INTEN &= 0xBF;
break;
case Adc7:
  AD0INTEN &= 0x7F;
break;
}
}

void ISR_ADC(void)  __irq
  {
if(AD0DR0 & 0x80000000)
ADCval[0]=((AD0DR0 & 0x0000FFF0)>>4); 
else if(AD0DR1 & 0x80000000)
ADCval[1]=((AD0DR1 & 0x0000FFF0)>>4);
  else if(AD0DR2 & 0x80000000)
ADCval[2]=((AD0DR2 & 0x0000FFF0)>>4);
  else if(AD0DR3 & 0x80000000)
ADCval[3]=((AD0DR3 & 0x0000FFF0)>>4);
else if(AD0DR4 & 0x80000000)
ADCval[4]=((AD0DR4 & 0x0000FFF0)>>4);
else if(AD0DR5 & 0x80000000)
ADCval[5]=((AD0DR5 & 0x0000FFF0)>>4);
else if(AD0DR6 & 0x80000000)
ADCval[6]=((AD0DR6 & 0x0000FFF0)>>4);
else if(AD0DR7 & 0x80000000)
ADCval[7]=((AD0DR7 & 0x0000FFF0)>>4);
}


Just use ADCval for channel results
0 Kudos

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Wed Jan 23 13:29:43 MST 2013

Quote: MikeSimmonds

I think the UM's are [I]very[/I] badly worded, ambiguous and self-contradictory in the ADC chapter.

...

Hey NXP Tech Guys! -- Please tell us if this is correct -- or give more details if not.



Wow wow wow ...
Normally I'm not this harsh but please take care of what you write. If you can't find what you are looking for then don't just blame the writer...
Especially on this issue (overrun) the manual is very clear:
This bit is 1 in burst mode if the results of one or more conversions was (were) lost 0 and overwritten before the conversion that produced the result in the RESULT bits.


So it indeed just tells you that one or more results have not been read before a new value was available.

With regard to the scan once Then stop mode that avass is looking for, this is possible when using hardware triggered mode using e.g. A timer match output. Set the bits of the channels you want to scan in the SEL bits, set BURST to 0 and any of the modes 010 to 111 in the ADCR register as described in the section "hardware triggered conversion".

Rob
0 Kudos

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MikeSimmonds on Wed Jan 23 10:06:21 MST 2013
[FONT=Tahoma][SIZE=2]
Quote:
Also, I wasn't sure if the overrun may signal incomplete sampling. For  example if the signal is always the same, would the overrun result be  the same ( not including noise ) or would it be a partial read?

[/SIZE][/FONT][FONT=Tahoma][SIZE=2]
(Warning: This is just my own interpretation, but it seems to be bourne out by experiment.)

I think the UM's are [I]very[/I] badly worded, ambiguous and self-contradictory in the ADC chapter.

My understanding is the the 'overrun' flags only say that a conversion result was stored before the last was read (a bit like the uart receive character register).
In my experience, the actual value store is correct and reads also get a correct (if out of date) result.

Hey NXP Tech Guys! -- Please tell us if this is correct -- or give more details if not.

Regards, Mike


[/SIZE][/FONT]
0 Kudos

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by avass on Tue Jan 22 12:18:11 MST 2013

Quote: MikeSimmonds
[FONT=Tahoma][SIZE=2]This may not help you, but ...

I couldn't find a way to do a [I]single[/I] burst with multiple channels, so I set it to run continuously.

I then just grab a result from a prticular channel as and when I want it.
I don't care about overrun; the result is correct (the last conversion done)
and it doesn't matter (to me) how many other conversions I might have missed
between the reads that I do.

It's a voltage representing a pair of light sensors and a temperature sensor -- all I really care about is
"What is the level/temp right now?"

As I said, this may not suit your requirements, but it simplified things a lot for my
project.

Mike

[/SIZE][/FONT]



Thanks Mike, this does help indeed. Right now I'm enabling sampling 2 more channels ( 6 altogether ), but interrupt at the 4th. With this there is no overrun ( as the conversion probably still processes the 5th or the 6th ), but it sounds like a really lame solution.

I'd much rather have something which says "scan only once than stop"...

Also, I wasn't sure if the overrun may signal incomplete sampling. For example if the signal is always the same, would the overrun result be the same ( not including noise ) or would it be a partial read?
0 Kudos

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by avass on Tue Jan 22 12:13:49 MST 2013

Quote: karanmehta93
Are you using Timer interrupt or ADC interrupts for this?
In case you want to know, use ADC interrupt which is triggered automatically whenever conversion on any channel completes. This will save your time. And you can always post your code for others.



Both. I use timer interrupts to trigger the burst and than the ADC intr to detect when the conversion is done and stop the conversions.

I can't afford to have the conversions being done continuously due to power requirements, thus the scheduled enable/disable.
0 Kudos

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by MikeSimmonds on Tue Jan 22 10:18:02 MST 2013
[FONT=Tahoma][SIZE=2]This may not help you, but ...

I couldn't find a way to do a [I]single[/I] burst with multiple channels, so I set it to run continuously.

I then just grab a result from a prticular channel as and when I want it.
I don't care about overrun; the result is correct (the last conversion done)
and it doesn't matter (to me) how many other conversions I might have missed
between the reads that I do.

It's a voltage representing a pair of light sensors and a temperature sensor -- all I really care about is
"What is the level/temp right now?"

As I said, this may not suit your requirements, but it simplified things a lot for my
project.

Mike

[/SIZE][/FONT]
0 Kudos

2,278 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by karanmehta93 on Tue Jan 22 07:45:10 MST 2013
Are you using Timer interrupt or ADC interrupts for this?
In case you want to know, use ADC interrupt which is triggered automatically whenever conversion on any channel completes. This will save your time. And you can always post your code for others.
0 Kudos

2,278 Views
torukoyama
Contributor I

Sorry to interrupt you.

I'm programming for LPC11U64, but not familior with LPC architecture yet. I have a question about the burst mode of this ADC.

Here is what I want to do.

My program needs to know if the analog input crosses the level of THR0_LOW. The ADC is set to the burst mode, I mean, CPU has to do some processes immediately after the analog input value crosses a certain point, then ADC is set to burst mode. Now I've got ADC_A_IRQ, but the reading of <THCMPCROSS> field of SEQA_GDAT register is always zero. Why? My expectation is 0x2(Downward) or 0x3(Upward), and <RESULT> field of SEQA_GDAT also seems to be wrong.

0 Kudos