Port-mapping refers to directly accessing the hardware registers (ports), in particular the input/output ports. Use this tag for discussing direct port access.

The Arduino libraries simplify accessing the processor hardware by providing high-level functions, such as pinMode, digitalRead and digitalWrite (amongst others).

Whilst they are easy to use, the simplicity generally has an overhead of loss of speed. Programmers who wish to access the hardware quickly will do "direct port access". For example (for the Atmega328P, such as used on the Arduino Uno):


pinMode

Instead of:

pinMode (3, OUTPUT);

Do:

DDRD |= bit (3);  // Port D, bit 3 to output mode

Instead of:

pinMode (13, INPUT);

Do:

DDRB &= ~bit (5);  // Port B, bit 5 to input mode

Instead of:

pinMode (8, INPUT_PULLUP);

Do:

DDRB &= ~bit (0);  // Port B, bit 0 to input mode
PORTB |= bit (0);  // Make Port B, bit 0 HIGH, to turn on pull-up resistor

digitalWrite

Instead of:

digitalWrite (7, HIGH);

Do:

PORTD |= bit (7);  // Make port D, bit 7, HIGH

Instead of:

digitalWrite (6, LOW);

Do:

PORTD &= ~bit (6);  // Make port D, bit 6, LOW

digitalRead

Instead of:

byte foo = digitalRead (5);

Do:

byte foo = (PIND & bit (5)) ? HIGH : LOW;

Warning

The port letters (eg. PINB, PINC, PIND) and the bit numbers (eg. bit(1), bit(2) etc.) are specific to each processor.

For ease of use, the library functions save working out exactly which port and bit numbers to use.


Timing

  • pinMode (2, OUTPUT); : 4.5625 µs (73 clock cycles)
  • DDRD |= bit (3); : 250 ns (4 clock cycles)

  • pinMode (13, INPUT); : 4.9375 µs (79 clock cycles)
  • DDRD &= ~bit (5); : 250 ns (4 clock cycles)

  • pinMode (8, INPUT_PULLUP); : 5 µs (80 clock cycles)
  • DDRB &= ~bit (0); PORTB |= bit (0); : 375 ns (6 clock cycles)

  • digitalWrite (7, HIGH); : 3.9375 µs (63 clock cycles)
  • PINB |= bit (4); : 250 ns (4 clock cycles)

  • digitalWrite (6, LOW); : 4.875 µs (78 clock cycles)
  • PINB &= ~bit (6); : 250 ns (4 clock cycles)

  • digitalRead (5); : 4.625 µs (74 clock cycles)
  • (PIND & bit (5)) ? HIGH : LOW; : 125 ns (2 clock cycles)

digitalWriteFast library

You can have the convenience of easy-to-use function calls and the speed of port mapping by using the digitalWriteFast library. Providing your pin numbers are constants (that is, not variables which might change at run-time) digitalWriteFast will automatically substitute the appropriate port-mapped I/O where appropriate. For example:

#include <digitalWriteFast.h>

void foo ()
  {
  digitalWriteFast (7, HIGH);
  byte bar = digitalReadFast (3);
  }

In this example, digitalWriteFast and digitalReadFast are as fast as the port-mapped access.