Reading multiple digital pins with one instruction

Is there a way to read multiple digital pins with one function call?

I think digitalRead/digitalWrite are actually reading the entire 8 bits of one parallel port,

and just masking off all bits except for the one passed as an argument to digitalRead/digitalWrite call.

The reason I need to do this is because my Arduino is monitoring 4 digital input pins,

and I want to make sure that only 1 pin changes at any one time.

The only way to do that is to read them all at once.

Can this be done using the Arduino language?

Yes it can be done. Try goggling “Arduino direct port manipulation”.

fll-freak:
Yes it can be done. Try goggling “Arduino direct port manipulation”.

I’ve measured the time it takes to change a single bit, using direct port vs digitalWrite()

using the code below.

digitalWrite() → 4uS

direct port → 139nS

That’s a lot more difference than I expected.

Also, note the difference in symmetry of the two waveforms.

const int pinSignal = 2;


#define DIRECT_PORT 1

void setup()
{
  
  #ifdef DIRECT_PORT
    DDRD = DDRD | B00000100;
  #else
    pinMode(pinSignal, OUTPUT);  
  #endif
  
}


void loop()
{
  
  #ifdef DIRECT_PORT
    PORTD &= ~0x04; // OFF
    PORTD = 0x04;   // ON
  #else
    digitalWrite(pinSignal, LOW);
    digitalWrite(pinSignal, HIGH); 
  #endif
  
}

It is way faster. I had to bit bang a serial interface to an LCD. Using the digitalwrite methods, you could watch the screen redraw. With the direct port manipulation the whole screen appeared to chage at the same time.

fll-freak:
It is way faster. I had to bit bang a serial interface to an LCD. Using the digitalwrite methods, you could watch the screen redraw. With the direct port manipulation the whole screen appeared to chage at the same time.

I haven’t been able to find any examples of serial interfaces to LCDs, for Arduino based projects.

Everything I’ve seen is for parallel LCDs.

The LCD I used was this one: http://www.sparkfun.com/products/8600

It is an SPI interface, but it wants 9 clocks! So I bit banged the data over.

There are other serial LCD devices as well. Some are just text; others are graphic in nature. Some are I2C or SPI. Some are RS-232 or CMOS level RS-232. Lots of choices; too little time.

fll-freak:
The LCD I used was this one: http://www.sparkfun.com/products/8600

It is an SPI interface, but it wants 9 clocks! So I bit banged the data over.

There are other serial LCD devices as well. Some are just text; others are graphic in nature. Some are I2C or SPI. Some are RS-232 or CMOS level RS-232. Lots of choices; too little time.

I can see where color/graphics would take more time.

I haven’t played with any LCDs yet, but i have a few lying around.

That will probably be my next Arduino project.

fll-freak:
It is way faster. I had to bit bang a serial interface to an LCD. Using the digitalwrite methods, you could watch the screen redraw. With the direct port manipulation the whole screen appeared to chage at the same time.

Yeah, it’s way faster. But would you care to comment why the symmetry is so different?

It looks like digitalWrite() intentionally incurs a delay to make successive calls result in a 50% duty cycle.

I’m not sure why they wanted to do that. Leave that up to the user.

I think the symmetry issue is just a red herring.

I can’t image the case where the authors of DigitalWrite changed its speed so that in an infinite loop it would cause a square wave. I think it just fell out that way.

One issue is that because the direct port method is it soooo much faster, you had to speed up the time scale on the scope. Now with that much detail, you are seeing the overlead of the loop. The high time is longer because that is the time the Loop routine is returning to the caller, and then getting called again.

In the other trace, that overhead is such a small part of the overall time that you can’t see the difference. Now get a very deep memory scope and pan through the data, and I will bet you see the same delta applied to the slow trace.

The overhead is fixed not proportional!