Go Down

Topic: Direct Port Access Analog Read (Read 10796 times) previous topic - next topic


I have seen alot of exmaples how to do direct port access to read / write to digital ports or to set the state of analog ports.
Does anyone now how to do a direct analog port read.  My application is dealing with 1-10 microsecond timing.  When I go to do a analogRead and it take 100microseconds it causes big problems.
An example would be very appreciated.


Even if You got some of the Analog port direct access funtions You'll be pleased. In the Arduino datasheet of the microcontroler is written that 10bit convertion of an analog signal takes up to 260us, and no way You can pass this. You can speed it up by reducing resolution of the ADC somehow. Don't remember how :/. In my case it wasn't possible. I've connected an external ADC (MCP3208) to arduino via softwareSPI, but I have the same speed as in internal arduino ADC (but with better resolution) and half of ma functions was low level digital port manipulations :/. Mayby my post will somehow help You. http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1265747580 I'm waiting for an answer on it with some hardwareSPI results.

(sorry for my English. I'm Polish)


The analog-digital conversion takes a while for sure(I actually thought it was tens of ms).

I believe you could do the conversion asynchronously though i.e. you start it and your program keeps running til the answer is ready then picks it up - would that help?


How would one go about doing it asynchronously?  That would be very helpful and would solve my problem.  


I saw it over on avrfreaks.  You set the ADC running continuously and it either posts an interrupt or you grab the result when you need it (I forget).

Try the following link http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=56429&postdays=0&postorder=asc


Feb 10, 2010, 10:00 pm Last Edit: Feb 10, 2010, 10:03 pm by mitch_79 Reason: 1
Go to the ADC section of your Atmega datasheet.  You'll find info like this (below) and more...

After it's started the ADC takes 13 ADC_clock ticks to capture a value.  The ADC_clock can be configured to run on divisors of 1, 8, 32, 64, 128 of the system clock I think.  Smaller divisors seemed to be more prone to noise.  I got pretty clean results on 100 Hz signals with divisor = 64, @ 8-bit precision.

So at 16 MHz, 64 * 13 -> 1 sample every 52 us max.

For your high-speed requirement you'll likely want to setup an interrupt to occur every time the ADC completes.  And then in the interrupt kick-off the next ADC.  Note that it takes another ~100 system clock ticks to get into the Interrupt routine.  Example code of this method for an Arduino mega below (running on channel 6 @ ADC_clock prescaler = 128)...

Warning:  don't use this code with the analogread/write Arduino environment functions.  It is likely to make a mess of things if you combine the two methods.

Code: [Select]

byte Channel6;

void setup() {
 // setup ADC
 ADMUX = B01100110;  // default to AVCC VRef, ADC Left Adjust, and ADC channel 6
 ADCSRB = B00000000; // Analog Input bank 1
 ADCSRA = B11001111; // ADC enable, ADC start, manual trigger mode, ADC interrupt enable, prescaler = 128

ISR(ADC_vect) { // Analog->Digital Conversion Complete
 char ADCch = ADMUX & B00000111;  // extract the channel of the ADC result
 if (ADCch == 6) {
   Channel6 = ADCH;  // store ADC result (8-bir precision)
   ADCSRA |= B11000000;  // manually trigger the next ADC

void loop() {

Go Up